之前有了解过悲观锁,乐观锁。但是由于业务场景的问题,悲观锁一直没有真正使用过。现在碰到了一个需要使用悲观锁的场景,特此自己做了实验并记录下来:
注:for update 仅适用于InnoDB,且必须开启事务(即查询语句要在begin与commit之间)。
以下实验的MySQL的事务隔离级别为repeatable_read:
例:表users结构如下
1、明确指定主键或者索引,并且可以找到相应的记录,加行级锁;
在客户端A执行:
select * from users where id=1 for update;
如果有找到对应的行记录,则加行锁。如果未找到id=1的user,则不加锁;
此时在客户端B:可以读取id=1的user信息,但不能修改该user的信息(要等到客户端A的事务提交之后)。可以往user表中插入新的数据、读取及修改其他user信息。
2、无主键、索引,不管是否可以在表中找到满足条件的记录,都会加表级锁;
在客户端A执行:
select * from users where username='admin' for update;
不管user表中是否有username='admin'的user,都会加上表级锁;
此时在客户端B:可以读取user表中的数据,但不可往user表中插入新的数据、不可修改user表的数据(要等到客户端A的事务提交之后)。
3、主键/索引不明确,不管表中是否包含满足条件的记录,都会加表级锁
在客户端A执行:
SELECT * FROM users WHERE id>100 FOR UPDATE;
不管user表中是否有id>100的user,都会加上表级锁;
此时在客户端B:可以读取user表中的数据,但不可往user表中插入新的数据、不可修改user表的数据(要等到客户端A的事务提交之后)。