为了保证数据的一致性,任何数据库都存在锁定机制。MySQL作为最常用的数据库,自然也不例外。 MySQL使用的主要存储引擎分为以下几种:
- MyISAM
- InnoDB
- NDB Cluster
- Maria
- Falcon
- Memory
- Archive
- Merge
- Federated
其中,使用最多最广泛的就是MyISAM和InnoDB,这里介绍锁定机制也主要探讨这2种存储引擎。 MySQL的锁定机制有3个级别:
- 行级锁定(row-level)
- 表级锁定(table-level)
- 页级锁定(page-level)
##行级锁定
属于最小的锁定粒度。因为锁定粒度很小,所以发生资源争用的概率也是最小的,能应对App最大的并发处理需求,提升性能。但也正是由于粒度小,使得每次获取和释放锁的时候需要的操作和消耗的资源也变得更多,也最容易发生死锁。使用这种锁定的引擎主要是MyISAM、Memory、CSV等。
##表级锁定
表级锁定是MySQL中锁定粒度最大的一种锁定。实现的逻辑最简单,系统处理锁使用的资源也最少,可以很好的避免死锁问题。当然,相对于行级锁定,并行处理的能力也由于对整个表的一次性锁定而大打折扣。使用这种锁定的引擎为InnoDB、NDB Cluster。
##页级锁定
属于MySQL中一种特殊的锁定机制。锁定某一类查询页的时候会用到(并不常用),粒度介于以上2种锁定之间,其他特性也相对如此。这种锁定方式为BDB的锁定形式。 先简单看一下表级锁定。 一般来讲,表级锁定分为读锁和写锁。MySQL通过4个队列来维护这2种锁定的信息:
- Current read-lock queue(lock->read)
- Pending read-lock queue(lock->read_wait)
- Current write-lock queue(lock->write)
- Pending write-lock queue(lock->write_wait)
很简单,从字面上就可以知道这些队列分别的公用。
##读锁
一个新的Client Requset Resources(Read读锁),需要满足以下2个条件:
- 请求锁定的资源上没有写锁。
- 写锁等待队列(Pending write-lock queue)中没有更高优先级(high-level-priority)的写锁在等待(获取资源)。
如果满足了以上的2个条件,那么当前Client立即获取资源,并加上读锁。
如果任一条件没有得到满足,这个请求会被迫进入等待队列(Pending read-lock queue)中等待资源的释放。
##写锁
当Client Requset Resources(Write写锁)的时候,MySQL首先会Check Current write-lock queue是否已经有锁定相同资源的信息存在。然后是检查Pending write-lock queue,如果有锁已经存在,则进入等待队列。
MyISAM引擎使用的锁机制完全是由MySQL提供的表级锁定实现的。下面以MyISAM引擎为例,对显式的加锁做一个演示:
显式给qqlist表加读锁,session之间的操作未被阻塞。
更新操作:当前拥有锁的session遇到加锁的错误,其他session的操作被阻塞。
释放读锁。其他session获取资源,操作顺利执行。
获取local read,其他线程的insert操作未被阻塞(Concurrent Insert特性)。
显式给qqlist表加写锁,其他session的读操作被阻塞。
释放写锁。其他session获取资源,操作顺利执行。
通过DDL(Alter table)获取WRITE_ALLOW_READ类型的写锁,其他session的读操作未被阻塞。
- 版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0
- 转载请注明:Chentao’s Home