MySQL学习系列
锁机制是为了解决数据库的并发控制问题而产生的。如在同一时刻,客户端对同一个表做更新或查询操作,为了保证数据的一致性,必须对并发操作进行控制。同时,在事务特性中,锁机制也为实现 MySQL 的各个隔离级别提供了保证。
锁的分类
广义上的锁分为乐观锁和悲观锁,它是一种概念不同的软件有各自的实现方式。在MySQL中乐观锁:被访问的数据不会被别人修改,因此先不加锁。如果在操作过程中发现数据被修改,则采用cas重新获取数据进行更新。悲观锁:被访问的数据随时都有可能被修改,因此访问数据之前,先对数据加锁。
MySQL中根据数据的占用粒度又分为共享锁、排它锁和意向锁。其中共享锁:允许事务读取一行数据,阻止其他事务对数据进行修改。排它锁:允许事务去读取或者修改一行记录,阻止其他事务对数据进行查询或者修改。意向锁:先进行表锁,成功后再进行行锁。意向锁之间相互兼容不会产生阻塞。为了实现表锁和行锁的共存,实现多粒度锁机制。
不同锁之间的兼容/互斥关系
MySQL中根据应用粒度不同还分为行锁、页锁和表锁。其中行锁基于索引实现,其锁定的粒度最小,因此对应的并发也更高,但上锁过程的判断较为复杂,上锁和释放过程都占用较多系统资源,容易产生死锁,代表引擎innodb。表锁与行锁的优缺点基本相反,表锁是针对整个表进行锁定的,其实现简单执行速度快,但由于锁的粒度较大导致并行度较低,代表引擎mylsam。页锁比较少见,顾名思义它是基于数据页进行上锁的,其特性基于上述两者之间,代表引擎BDB。
从MySQL的实现进行分类锁包括以下几种:
自增长锁:对于自增长id进行插入时如采用表级锁则影响性能;mysql提供了auto_lock_model来处理自增长问题。如果设置为0(插入完成后释放,即便事务未提交也释放锁);1(判断自增长需要使用的数字后立即释放锁,事务回滚会导致不连续),2 直接分配,不使用锁,性能较好,但主键可能不连续。它是一种特殊的表级锁,特定应用在事务插入aotu_increatment类型的列。它能够保障同一个事务插入数据的顺序性;如果是非自增列,则使用插入意向锁(gaplock的一种),在插入位置不冲突的情况下它并不会阻塞彼此。
外键锁:当插入和更新子表时,首先检查父表记录,这可能对数据的检索造成阻塞,不建议增加外键。
Record lock:单条记录上的锁。
Gap lock:间隙锁,锁定一个范围但不包括记录本身。
Nextkey lock:临键锁,record lock+gap lock 锁定一个范围并锁定数据本身。
间隙锁和临键锁都只在RR事务隔离级别下有效,临键锁能够在可重复读的事务隔离级别下协助解决幻读问题,避免串行化重量级锁对性能的影响。