水下功夫做透,水上才能顺风顺水。

mysql InnoDB的行锁

InnoDB 存储引擎锁类型主要记住下面两句话就够了:

事务本事(自事务)不存在任何隔离性。 

1)        读写锁,实现读读并发。  2)        一致性非锁定读( MVCC ),实现读写并发。

对于mysql InnoDB引擎(一个事务内既可以获取共享锁,同时可以获取排他锁。):

select 默认不加锁,快照读,不受其他事务锁的限制。
select ...for update 加排他锁,(我要读取最新已提交的数据且准备修改,防止在我读取的过程中,其他事务修改)
select ... lock in share mode加共享锁,(我要读取最新已提交的数据但不准备修改【因为很容易出现死锁】,防止在我读取的过程中,其他事务修改)

时间

会话 A

会话 B

1

begin

 

2

select * from t where id=3 lock   in share mode;

获得了 S 锁

 

3

 

begin

4

 

select * from t where id=3 lock   in share mode;

获得了 S 锁

5

update t set name='baiyadong'   where id = 3;

等待会话 B 释放 S 锁

 

6

 

update t set name='baiyadong'   where id = 3;

检测到死锁,会话 B 回滚

7

执行成功

 

一个事务获取了共享锁,其他事务可以获取共享锁,不能获取排他锁。一个事务加共享锁,可以对该条记录进行读写。两个回话都加共享锁,均可以对该条记录进行读,都无法写。
update,delete,insert默认加上排他锁。

一个事务T对数据A加上排他锁后,既可读又可写,其他事务不能再对A加任任何类型的封锁。
一条记录不管是被加排它锁还是共享锁,其它select默认都可以读取执行。

 

在MVCC并发控制中,读操作可以分成两类:快照读 (snapshot read)与当前读 (current read)。快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。

当前读:每次读都加锁,不允许其他事务对数据进行修改。比如update,delete, select for update ,select in share mode.读的是最新数据(如果其他事务有更新、删除、插入未提交,则该操作阻塞,直至对方事务提交。)。也叫一致性锁定读。     

快照读:select读的是历史版本。就是通过mvcc实现的。也就一致性非锁定读。

隔离级别是如何实现的?mvcc,多版本并发控制

RU :读mvcc版本链中的最新数据。

RC:mvcc读取规则。

RR:mvcc读取规则。

Serializable:  普通的select都加锁,完全串行化了,没有 MVCC。

 

InnoDB 存储引擎如何利用锁实现四种事务隔离级别

按照 SQL92 标准, InnoDB 使用不同的锁策略实现了四种不同事务隔离级别。

未提交读

READ-UNCOMMITTED

select 语句不加锁,会出现脏读。

隔离性最差,并发最高

串行化

SERIALIZABLE

select 语句隐式转换为 select … in share mode ,与 X 锁互斥。

一致性最好,并发最差,如果有未提交的修改,所有读取这些行的 select 都会被阻塞,没有 MVCC。

可重复读

REPEATABLE-READ

普通 select 是 MVCC 。

锁定读 /update/delete 使用 Record Lock 和 Next-Key Lock ,防止幻影记录出现。

InnoDB 默认的隔离级别。

提交读

READ-COMMITTED

普通 select 是 MVCC 。

锁定读 /update/delete 使用 Record Lock ,可能出现不可重复读。

 

MySQL 存储引擎 InnoDB 隔离级别 RR 解决了幻读问题。

posted @ 2020-02-08 20:08  北方寒士  阅读(358)  评论(0编辑  收藏  举报