InnoDB存储引擎使用3种行锁的算法:
- Record Lock:单个行记录上的锁
- Gap Lock:间隙锁,锁定一个范围
- Next-key Lock:Gap Lock+Record Lock 锁定本身以及下一个范围
InnoDB对行的查询采取Next-key Lock算法。
例如,包含索引10 11 13 20 采取Next-key Lock方式,锁定的区间为:
- (10,11】
- (11,13】
- (13,20】
插入新的记录12后:
- (10,11】
- (11,12】
- (12,13】
- (13,20】
【锁问题】
锁的机制可以实现事务之间的隔离性,使得事务并发的进行工作,锁可能引起的三类问题:
①脏读
脏页:缓冲区中已经修改的页(已经提交),但还没有刷新到磁盘,即内存中的页和磁盘上的页不一致。但是日志一定已经写入到Redo重做日志中了。
脏读:事务对缓冲区的修改,还没有提交,而其它事务读取了这部分内容
对脏页的读取,是合理正常的,脏页只是由于数据库实例内存数据还没有同步到磁盘上造成的,但并不影响数据的一致性。
因为两者最终会达到一致性,即:磁盘上的数据最终会更新到和内存中一致。
而对脏数据的读取,则违反了数据库事务之间的隔离性。脏读只在事务的隔离级别为Read Uncommitted情况下发生。
为什么事务需要提供读未提交的隔离级别?
:在一些特殊情况下,例如replication环境中的Slave节点,并且该节点查询不需要特别精确的返回值
②不可重复读
同一个事务多次读取同一个数据集合,而另一个事务在期间修改了数据,造成前后读取的变化。
其与脏读的区别在于,其读取到的是其它事务已经提交的数据。 大部分数据库厂商将隔离级别设定为Read Committed 在此隔离级别下,将可能发生不可重复读,其取决于实际业务场景对隔离级别的要求。
③丢失修改
一个事务的更新操作被另外一个事务更新所覆盖
一个典型的丢失修改的过程:
- 事务T1查询一行数据,放入本地内存,并显示给一个用户User1
- 事务T2查询该行数据,放入本地内存,并显示给一个用户User1
- User1修改该行记录,更新数据库提交
- User2修改该行记录,更新数据库提交