参考:
本文只是对于“SELECT ... LOCK IN SHARE MODE”和“SELECT ...
FORUPDATE”事务中的锁和RR隔离级别内的测试,针对于表结构、索引结构以及其他隔离级别情况下的触发锁类型,可以参考网易何登成网盘中“MySQL
加锁处理分析.pdf”这篇文章,很细致。
何登成百度网盘:
下面的内容是参考上面链接博文测试的内容,文字略加修改,方便自己查询和阅读。
测试一:
<col>
Variable_name
Value
tx_isolation
REPEATABLE-READ
session 1
session 2
1
update未提交
select
update t1 set b=‘z‘
where a=1
select * from t1
session 1 commit之前,普通select返回的结果都是session 1
commit提交前结果
2
select … lock in share mode
update t1 set b=‘y‘
where a=1 lock in
share mode
session 1 commit以后session 2返回结果
3
select … for update
update t1 set b=‘x‘
where a=1 for
update
RR的隔离级别,对于a=1行的update操作会给行加排他锁
1、普通的select只是对于session
1事务提交前的行数据快照查询
2、select … lock in share mode属于共享锁,与session
1的排他锁互斥,需要等待session 1提交或者回滚
3、select … for update属于排他锁,与session
1的排它锁互斥,所以也需要等待需要等待session 1提交或者回滚
测试二:
query
result
begin
select * from t1 where a=1 for update
4
update t1 set b=‘u‘ where a=1
session 2查询需要等待session 1事务处理完成或者回滚
5
select * from t1 where a=1 for
或
select * from t1 where a=1 lock in share mode
无返回,等待
6
select * from t1 where a=1 for
+---+------+
| a | b |
| 1 | u
|
1 row in set (0.00 sec)
session 2查询需要等待session 1事务处理完成或者回滚
7
commit
1 row in set (33.02 sec)
8
update t1 set b=‘w‘ where a=1
session 1事务处理完成或者回滚后session 2获得查询结果
9
| 1 | w
10
session 2事务处理完成或者回滚后session 1获得查询结果
11
12
1 row in set (10.46 sec)
测试三:
session
2事务虽然只有一个select但是由于update和select两个所持有的共享锁、排他锁互斥,所以session
1的update事务需要等到session 2提交以后完成
update t1 set b=‘m‘ where a=1
Query OK, 1 row affected (17.49 sec)
Rows matched: 1 Changed: 1 Warnings: 0
select * from t1 where a=1 lock in share mode
session 1未提交事务,等待
| 1 | m
1 row in set (7.16 sec)
此后又做了几个测试,总结如下:
type
类型
快照
select … lock in share mode
共享锁
select … for update
排它锁
DML
共享实时
互斥等待