悲观锁按照使用的性质可以划分为共享锁(Share Lock)和排他锁(Exclusive Lock)。
关于排他锁的使用,可以见另一篇博客MySQL之悲观锁(select for update)的使用,本文主要介绍共享锁的使用。
共享锁(Share Lock)
S锁,又称读锁,用于所有的只读数据操作。共享锁是非独占的,允许多个并发事务读取其锁定的资源。
性质: 1,多个事务可以封锁同一个共享页。 2,任何事物都不能修改该页。 3,通常该页被读取完毕后,S锁会被立即释放。
允许不同事务之前共享加锁读取,但不允许其他事务修改或者加入排他锁。
如果有修改必须等待一个事务提交完成,才可以执行,容易出现死锁。
例如:
select * from books where book_id = 7 lock in share mode;
共享事务锁之间的读取
sesison 1:
start transaction;
select * from books where book_id = 7 lock in share mode;
session 2:
start transaction;
select * from books where book_id = 7 lock in share mode;
此时,两个会话均能正常的查询到数据。
session 3:
start transaction;
select * from books where book_id = 7 for update;
此时进入了等待的状态。返回如下错误:
1205 - Lock wait timeout exceeded; try restarting transaction, Time: 51.019000s
共享锁之间的更新
当session1 执行了修改语句:
sesison 1:
update books set name = “H5” where book_id = 22;
进入等待状态。。
session 2中执行相同的SQL,提示死锁,显示如下错误:
1213 - Deadlock found when trying to get lock; try restarting transaction, Time: 0.078000s
只有session1执行了commit操作,才会释放S锁,session2才能执行update操作。
若多个session并发执行,出现死锁的概率将大大增加。
总结
MySQL 共享锁(lock in share mode)
- 允许其他事务也增加共享锁读取
- 不允许其他事务增加排他锁(for update)
- 当事务同时增加共享锁时,事务的更新操作必须等待先执行的事务commit后才能执行,如果同时并发太大的时候很容易造成死锁。