InnoDB提供一致性非锁定读
,行级锁
支持。行级锁没有相关额外的开销,并可以同时得到并发性和一致性。
lock | latch | |
---|---|---|
对象 | 事务 | 线程 |
保护 | 数据库内容 | 内存数据结构 |
持续时间 | 整个事务过程 | 临界资源 |
模式 | 行锁,表锁,意向锁 | 读写锁,互斥量 |
死锁 | 通过wait-for graph,time-out等机制进行死锁检测和处理 | 无死锁检测和处理 |
存在于 |
InnoDB实现了两种标准行级锁:共享锁
和排他锁
。为了支持在不同粒度
上进行加锁操作,支持一种额外的锁方式意向锁
在InnoDB中其意向锁即为表级别的锁。IS Lock,事务想要获得一张表中某几行的共享锁,IX,事务想要获得一张表中某几行的排他锁。由于InnoDB存储引擎支持的是行级别的锁,因此意向锁不会阻塞除全表扫描以外的任何请求。
一致性非锁定读
如果读取的数据正在delete或者update,这时读取操作不会等待行上的锁释放,InnoDB会去获取行的历史数据,这个数据是undo用于回滚的,不会产生额外开销,此外读取快照数据不需要上锁,因为没有事务需要对历史数据进行修改。在不同的事务隔离级别下,非一致性读对快照的定义不同,Read Committed
事务隔离级别下,对于快照数据,非一致性读总是读取被锁定行
的最新
一份快照数据,而在Repeatable Read
事务隔离级别下,对于快照数据,非一致性读总是读取事务开始
时的行数据版本。
一致性锁定读
InnoDB存储引擎对于SELECT语句支持两种一致性的锁定读。SELECT... FOR UPDATE
, SELECT LOCK IN SHARE MODE
。SELECT … FOR UPDATE 对读取的行记录加一个X锁,其他事务不能对已锁定的行加任何锁。SELECT… LOCK IN SHARE MODE 对读取的行加一个S锁,其他事务可以向被锁定的行加S锁,如果加X锁,则会被阻塞
自增长与锁
自增长的计数器值加1赋予自增长列,使用AUTO-INC LOCKING。这种锁使用的表锁机制,在完成对自增长值插入的SQL语句后立即释放。
5.1.22版本开始,InnoDB提供了一种轻量级互斥量的自增长实现机制。
插入类型
插入类型 | 说明 |
---|---|
insert-like | 指所有的插入语句如:Insert, Replace,Insert…Select, Replace…select, load data |
simple inserts | 插入前就确定插入行数的语句,包括Insert, Replace等不包括Insert… ON DUPLICATE KEY等 |
bulk inserts | 插入前不能确定得到插入行数的语句 |
mixed-mode inserts | 有一部分是自增长的,有一部分是确定的 |
对于“simple inserts”该值会用互斥量(mutex)对内存中的计数器进行累加操作, 对于“bulk inserts”还是使用AUTO-INC Locking。
锁的算法
InnoDB行锁的三种算法:
- Record Lock:单个行记录上的锁
- Gap Lock:间隙锁,锁定一个范围,但不包含记录本身。
- Next-Key Lock:Gap Lock + Record Lock, 锁定一个范围,且包含记录本身。
Next-Key Locking主要是为了解决幻读问题。当查询的索引含有唯一属性时,InnoDB存储引擎会对Next-Key Lock进行优化,将其降级为RecordLock,即锁住索引本身,而不是范围。
数据库死锁
死锁是指两个或两个以上的数据库事务在执行过程中,因争夺锁资源而造成的一种相互等待的现象。
解决死锁的方法:
-
将任何的等待都转化为回滚,并且事务重新开始。
-
两个事务相互等待时,超过时间阈值等待的事务进行回滚,另一个等待的事务就能继续执行。可能会造成权重比大的事务被回滚了。
-
wait-for graph的方式检测死锁。innodb选择回滚undo量最小的事务。