数据库锁(Lock)针对的对象是事务,用于锁定数据库中的表、页、行。一般lock的对象只有在事务commit或者rollback之后才会释放.
1. 锁类型(InnoDB实现了两种行级锁)
1.1 行级锁
共享锁 (S Lock):允许事务读一行数据
排他锁(X Lock):允许事务删除或者更新一行数据
1.2 锁的兼容
若事务T1获得了行r的共享锁,则事务T2可以立即获得行r的共享锁,该情况称为锁兼容.
若事务T3想要获取行r的排它锁,则必须等待事务T1和T2释放行r的共享锁,该情况称为锁不兼容.
X锁与S锁都是行级锁,X锁与任何锁都不兼容,S锁仅与S锁兼容.
1.3 意向锁
意向共享锁(IS Lock):事务想要获取一张表中某几行的共享锁
意向排他锁(IX Lock):事务想要获取一张表中某几行的排他锁
意向锁将锁定的对象(事务)分为多个层次,意味着事务希望在更细粒度上进行加锁操作。
例如:事务T需要对记录r加X锁,则事务需要分别先对数据库A、表、页上意向锁IX,最后才能对行r上X锁。若其中任何一部分导致等待,那么该操作需要等待粗粒度锁完成.
InnoDB各种锁的兼容性
* | IS | IX | S | X |
---|---|---|---|---|
IS | 兼容 | 兼容 | 兼容 | 不兼容 |
IX | 兼容 | 兼容 | 不兼容 | 不兼容 |
S | 兼容 | 不兼容 | 兼容 | 不兼容 |
X | 不兼容 | 不兼容 | 不兼容 | 不兼容 |
2. 一致性非锁定读
通过行多版本控制的方式来读取当前执行时间数据库中行的数据。如果在读取的行正在执行DELETE或者UPDATE操作,这时读取操作不会等待行上排他锁的释放,会去读取一个快照数据,该快照数据通过undo字段来完成。undo字段用于在事务中回滚数据,因此快照数据本身没有额外开销.
非锁定读在InnoDB存储引擎上默认开启,使得读取操作不会占用和等待表上的锁,从而可以极大的提高数据库的并发性.
关于快照数据的定义
数据库的事务有隔离级别(read uncommit 、read commited 、 repeatable read 、serializable),在不同的事务隔离级别下,快照数据的定义有所不同(InnoDB的默认隔离级别为repeatable read).
read commited :读取被锁定行的最新一份数据(PS: 在事务T1进行过程中,有其他事务T2更改该行数据并提交,则T1再次读取时会获得最新数据).
repeatable read : 读取事务开始时的行数据版本(PS: 在事务T1进行过程中,有其他事务T2更改该行数据并提交,则T1再次读取时数据依旧是T1开始时的数据).
3. 一致性锁定读
InnoDB的SELECT操作默认使用一致性非锁定读, 但用户可以显示的对数据库读取操作进行加锁以保证数据逻辑的一致性.
InnoDB对SELECT语句支持两种一致性锁定读操作:
SELECT … FOR UPDATE : 对读取的行记录加X锁.
SELECT … LOCK IN SHARE MODE:对读取的行记录加S锁.
- 上述两个操作需要在事务中进行,事务提交(或者回滚)后锁会被释放.
参考文献
[1] MySQL技术内幕InnoDB存储引擎