转自 https://www.jianshu.com/p/ed896335b3b4

4461377-700c97c4f6645b4f.png

共享锁&排它锁

innodb 实现的行级锁:
共享锁(S Lock):允许事务读一条数据
排它锁(X Lock):允许事务删除或跟新一条数据
锁兼容:只有两个共享锁

innodb默认情况下对select操作使用一致性非锁定读。
但是某些情况下,需要对select显示加锁
共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE

意向锁

意向锁:innodb支持多粒度锁定,允许行锁和表锁同时存在,不同粒度的加锁方式,成为意向锁。
意向共享锁(IS Lock):一个事务想获得一个表中某几行共享锁。
意向排它锁(IX lock):一个事务想获得一个表中的某几行排它锁。

乐观锁和悲观锁

乐观锁

读取数据认为别人不会修改,所以不加锁,在更新操作时判断一下在此期间别人有没有修改数据。

乐观锁实现方式

version:
在表中加一个数据库版本号(数字类型) 字段,读的时候连同version字段一同读出,更新的时候判断version条件等于刚读出的version,并对其+1. 如果不相等,则认为失败,不提交更新。
同理,时间戳字段也适用。

注意:读写分离情况下,存在同步延迟问题,此时要强制读master。

悲观锁

每次更新操作过程使数据处于锁定状态,一般使用数据库锁机制。

悲观锁的实现方式

可以通过innodb的排它锁实现:select ... for update.

锁问题

脏读

脏读和脏页不同。

脏页

脏页:在缓冲池中已经被修改的页,但是还没有刷新到磁盘,即内存和磁盘中的数据是不一致的,当然在刷新到磁盘之前,数据都写入到重做日志中了。

脏数据

指的是在缓冲区被修改的数据,但是还没有被提交。

脏读

就是指在不同事务下,读到其他事务未提交的数据,即读到脏数据。

不可重复读

也称提交读,就是一个事务能读到其他事务提交的数据。这造成一个事务两次读的数据可能不一致。
innodb通过next-key lock 算法来解决不可重复读。官方文档将不可重复读称为幻读。在next-key算法下,对于索引的扫描,不仅锁住扫描到的索引,还会锁住索引覆盖的范围(gap)。因此避免其他事务在这个范围内插入数据导致的幻读问题。

死锁

两个事务都等对方先释放。

回滚

innodb事务根据information_schema.INNODB_TRX表的trx_weight 事务权重(代表事务锁住的行数) 选择值较小的回滚。

锁的命令

1. 查看当前请求锁的信息:
show engine innodb status\G;

2. 事务表 information_schema.INNODB_TRX
3. 事务的锁表 information_schema.INNODB_LOCKS
4. 事务阻塞等待表 information_schema.INNODB_LCOK_WAITS

标签: none

添加新评论