MySQL 中的锁可以按照粒度分为锁定整个表的表级锁(table-level locking)和锁定数据行的行级锁(row-level locking):
InnoDB 实现了以下两种类型的行锁:
在 mysql 中,当表级锁和行级锁同时存在时,比如事务 A 先获取了行级锁,事务 B 申请表锁(进行表结构修改),如果事务 B 申请成功,需要修改表中的数据会因为事务 A 获取了行级锁从而造成冲突。
InnoDB 引入了 意向锁,意向锁是一种表级锁,由 InnoDB 自动添加,不需要用户干预。意向锁也分为共享和排他两种方式:
务 A 必须先申请该表的意向共享锁,成功后再申请数据行的行锁。事务 B 申请表锁时,数据库查看该表是否已经被其他事务加上了表级锁;如果发现该表上存在意向共享锁,说明表中某些数据行上存在共享锁,事务 B 申请的写锁会被阻塞。
因此,意向锁是为了使得行锁和表锁能够共存,从而实现多粒度的锁机制
当使用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是是所谓的间隙锁(GAP锁)。
InnoDB中,除单个SQL组成的事务外,锁是逐步获得的,这就决定了InnoDB发生死锁是可能的。
发生死锁后,InnoDB一般都能自动检测到,并使一个事务释放锁并退回,另一个事务获得锁,继续完成事务。但 InnoDB 并不能完全自动检测到死锁,需要通过设置锁等待超时参数innodb_lock_wait_timeout来解决。
todo
todo