mysql悲观锁是行锁还是表锁?
Posted 我爱看明朝
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql悲观锁是行锁还是表锁?相关的知识,希望对你有一定的参考价值。
mysql悲观锁是行锁还是表锁?
结论
悲观锁在非主键、非索引时是表锁,在主键、索引时是行锁。
使用悲观锁
在查询语句后面加上 for update 开启悲观锁。
select * from table where col = xx for update;
悲观锁: 在事务执行开始加锁,此时其他事务无法读写,等待事务完成,其他事务才可以获得这个锁。
验证悲观锁
-
关闭自动提交 set @@autocommit = 0; (设置事务是手动提交。 0: 手动提交 1: 自动提交,默认)
-
确认当前提交方式 select @@autocommit;
-
提交事务 commit;
示例验证
表user,id为主键,name没有索引
示例1
事务1
set @@autocommit = 0; //步骤1
select * from user where id = 1 for update; // 步骤4
commit; // 步骤7
事务2
set @@autocommit = 0; // 步骤2
select * from user where id = 2 for update; // 步骤5
commit; // 步骤8
事务3
set @@autocommit = 0; // 步骤2
update user set name = '12' where id = 1; //步骤6
commit; //步骤9
步骤1~9按照顺序执行,我们可以看到:
步骤7没有执行,步骤6会一直等待;步骤5不需要等待步骤7,可以看到这里是行锁。
示例2
事务1
set @@autocommit = 0; //步骤1
select * from user where name = '123' for update; // 步骤4
commit; // 步骤7
事务2
set @@autocommit = 0; // 步骤2
select * from user where name = '456' for update; // 步骤5
commit; // 步骤8
事务3
set @@autocommit = 0; // 步骤2
update user set age = 12 where name = '123'; //步骤6
commit; //步骤9
步骤1~9按照顺序执行,我们可以看到:
步骤7没有执行,步骤5,6会一直等待;和示例1的表现不一样,可以看到是表锁。
再回顾一下结论: 悲观锁在非主键非索引时是表锁,在主键索引时是行锁。
乐观锁
乐观锁: 事务不加锁,不对读写加锁,更新时根据版本号或时间戳判断是否可以更新。
例如表: user, 使用乐观锁,我们新加long型字段version。
// 伪代码
public void update (long id)
// 查询
User user = UserDao.selectbyId(id);
// 一通业务操作
do something
// 更新某个字段
int res = update user set cols = xx, version = verison + 1 where id = xx1 and version = user.version;
if (res != 1)
// 自旋重新执行业务,进行更新
我们可以看到乐观锁对比悲观锁,消耗的资源小,不影响其他业务。
两者对比
类型 | 考虑冲突时间 | 优点 | 悲观 |
---|---|---|---|
悲观锁 | 开始就考虑加锁 | 能够严格保证同步 | 效率低下 |
乐观锁 | 更新时才考虑 | 效率较高 | 自旋浪费cpu |
以上是关于mysql悲观锁是行锁还是表锁?的主要内容,如果未能解决你的问题,请参考以下文章