背景:在并发访问的环境中,如多个事务同时访问并尝试修改同一行数据时为了解决数据一致性问题,使用SELECT ... FOR UPDATE
允许事务在选择数据的同时,锁定这些数据,防止其他事务修改
这些数据,直到当前事务完成并释放锁。从本质上,SELECT ... FOR UPDATE
是一种悲锁的用法,一般情况下,只会锁住一行数据,但是如果没有正确使用的话,会把整张表都锁住的。
注意:
- 在mysql中Update、Delete、Insert命令都是会启用行级锁,如果Select命令要启动行级锁需要加上FOR UPDATE
- 而表级锁的命令包括ALTER TABLE、LOCK TABLES以及一些DDL语句(例如CREATE、DROP和TRUNCATE)。这些命令会锁定整个表
对于主键字段:
假设现在有一个事务1使用FOR UPDATE加行级锁(这里还没有提交事务):
START TRANSACTION; -- 开启事务 SELECT * FROM user_info WHERE id = 1 FOR UPDATE; -- 加行锁
此时有事务2执行以下命令
UPDATE user_info SET amount = 10000 WHERE id = 1
会报错:
1205 - Lock wait timeout exceeded; try restarting transaction
这就表明当一个事物使用行级锁并且还没有提交的时候,行级锁不会释放,另一事务就无法对数据进行操作。
总结一下SELECT ... FOR UPDATE
加锁的情况:
- 主键字段:加行锁。
- 唯一索引字段:加行锁。
- 普通索引字段:加行锁。
- 普通字段:加表锁。