// 读锁
select ... lock in share mode
// 写锁
select ... for update
假设有张 user 表,表中数据如下
------------------A事务------------------ | ------------------B事务------------------ |
---|---|
对 id = 1 的数据增加读锁,但是并不提交事务 ![]() |
|
不加锁的查询,查询成功 ![]() |
|
加上读锁查询,查询成功 ![]() |
|
对 id = 2 的数据进行修改,修改成功 ![]() |
|
对 id = 1 的数据进行修改,修改出现阻塞 ![]() |
|
事务提交 ![]() |
由于 A事务 commit 了,阻塞状态取消,修改成功 ![]() |
------------------A事务------------------ | ------------------B事务------------------ |
---|---|
对 id = 1 的数据增加写锁,但是并不提交事务 ![]() |
|
不加锁的查询,查询成功 ![]() |
|
加上写锁查询 id = 2 的数据,查询成功 ![]() |
|
加上写锁查询 id = 1 的数据,查询出现阻塞 ![]() |
|
事务提交 ![]() |
由于 A事务 commit 了,阻塞状态取消,查询成功 ![]() |
对 id = 1 的数据增加写锁,但是并不提交事务 ![]() |
|
修改 id = 2 的数据,修改成功 ![]() |
|
修改 id = 1 的数据,修改出现阻塞 ![]() |
|
事务提交 ![]() |
由于 A事务 commit 了,阻塞状态取消,修改成功 ![]() |
注意注意注意:for update 仅适用于InnoDB,并且必须开启事务,在begin与commit之间才生效。或者在代码中使用@Transactional才能生效。
行锁:访问数据库的时候,锁定整个行数据,防止并发错误。 如InnoDB存储引擎使用行锁
表锁:访问数据库的时候,锁定整个表数据,防止并发错误。 如MyISAM存储引擎使用表锁
例1:明确指定主键,并且数据真实存在,行锁
select status from t_goods where id = 1 for update;
例2:明确指定主键,但数据不存在,无锁
select status from t_goods where id = 0 for update;
例3:主键不明确,表锁
select status from t_goods where id <= 3 for update;
例4:无主键,表锁
select status from t_goods for update;
原文:https://www.cnblogs.com/luchaoguan/p/15149120.html