select .... for update究竟锁表还是锁行?
文章目录
- 介绍
- 实例验证
- 实例前准备数据
- 实例1--验证通过主键索引查询会锁行
- 实例2--验证通过普通索引作为查询条件会锁行
- 实例3--验证查询条件不命中索引会锁表
- 实例4--验证联合索引匹配到第一个字段也会锁行
- 实例5--验证关联表情况下关联条件是索引会锁行
- 实例6--验证关联表情况下关联条件不是索引只会锁行
- 结论
- 参考
介绍
select查询语句是不会加锁的,但是select …for update除了有查询的作用外,还会加锁呢,而且它是悲观锁。
在接触到这个语句之前,我一直认为它是加行锁的,但是我看有些文章是要看索引,因此我想做一个深入了解。
实例验证
实例前准备数据
user表
CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`age` int(11) DEFAULT NULL,`code` varchar(255) DEFAULT NULL,`prov_id` int(11) NOT NULL,`prov_code` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`),KEY `idx_age` (`age`) USING BTREE,KEY `user_prov_id_IDX` (`prov_id`,`code`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1570069 DEFAULT CHARSET=utf8;
prov_info表
CREATE TABLE `prov_info` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(50) DEFAULT NULL,`code` varchar(10) DEFAULT NULL,PRIMARY KEY (`id`),KEY `prov_info_code_IDX` (`code`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8;
user数据:
INSERT INTO test.`user`
(id, name, age, code, prov_id, prov_code)
VALUES(1, '测试1', 46, '0001', 21, 'K001');
INSERT INTO test.`user`
(id, name, age, code, prov_id, prov_code)
VALUES(2, '测试2', 20, '0002', 22, 'K002');
INSERT INTO test.`user`
(id, name, age, code, prov_id, prov_code)
VALUES(3, '测试3', 10, '0003', 23, 'K003');
prov_info数据
INSERT INTO test.prov_info
(id, name, code)
VALUES(21, '极阴岛', 'K001');
INSERT INTO test.prov_info
(id, name, code)
VALUES(22, '小环岛', 'K002');
INSERT INTO test.prov_info
(id, name, code)
VALUES(23, '中岛', 'K003');
在Dbeaver开启两个会话,分别作为事务1和事务2,设置事务1不自动提交
-- 关闭自动提交
select @@autocommit;set @@autocommit = 0;
实例1–验证通过主键索引查询会锁行
在事务1中对id=1,使用id作为查询条件,执行for update,不提交
在事务2中执行update语句
事务1:
select * from test.`user` u where u.id = 1 for update;
结果图:
事务2:(自动提交)
update test.`user` u set age = 46 where u.id = 1;
update test.`user` u set age = 20 where u.id = 2;
更新id=1的数据阻塞,更新id=2的数据没有阻塞
可以证明是锁行,如果是锁表的话,id=2的数据也会阻塞
实例2–验证通过普通索引作为查询条件会锁行
将之前事务提交。
在事务1中对id=3,使用age作为查询条件,执行for update,不提交
在事务2中执行update语句
事务1:
select * from test.`user` u where u.age = 10 for update;
结果图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/301d7c88014a4031b516c0cd1ea496e8.png
事务2:(自动提交)
update test.`user` u set age = 20 where u.id = 2;
update test.`user` u set age = 20 where u.id = 3;
更新id=3的数据阻塞,更新id=2的数据没有阻塞
可以证明是锁行
实例3–验证查询条件不命中索引会锁表
将之前事务提交。
在事务1中对id=3,使用code作为查询条件,执行for update,不提交
在事务2中执行update语句
事务1:
select * from test.`user` u where u.code = '0003' for update;
结果图:
事务2:(自动提交)
update test.`user` u set age = 20 where u.id = 2;
update test.`user` u set age = 20 where u.id = 3;
更新id=3的数据阻塞,更新id=2的数据也会阻塞
由此可以证明是锁表
实例4–验证联合索引匹配到第一个字段也会锁行
这个实例跟实例2相同,只不过我想看看联合索引只匹配第一个字段是不是也可以锁行
事务1:
select * from test.`user` u where u.prov_id = 23 for update;
事务2:
update test.`user` u set age = 20 where u.id = 2;
update test.`user` u set age = 20 where u.id = 3;
结果:
更新id=3的数据阻塞,更新id=2的数据没有阻塞
由此可以证明对于联合索引来说,只要命中了索引就可以锁行(联合索引要按顺序)
实例5–验证关联表情况下关联条件是索引会锁行
事务1:
select * from test.`user` u
inner join test.prov_info pi2 on u.prov_id = pi2 .id
where u.prov_id = 23 for update;
事务2:
update test.`user` u set age = 20 where u.id = 2;
update test.`user` u set age = 20 where u.id = 3;
UPDATE test.prov_info SET name='小环岛', code='K002' WHERE id=22;
UPDATE test.prov_info SET name='中岛', code='K003' WHERE id=23;
结果:
user表id=2的数据没有阻塞,id=3的数据阻塞,是锁行
prov_info表id=22的数据没有阻塞,id=23的数据阻塞,是锁行
实例6–验证关联表情况下关联条件不是索引只会锁行
事务1:
select * from test.`user` u
inner join test.prov_info pi2 on u.prov_code = pi2 .code
where u.prov_id = 23 for update;
事务2:
update test.`user` u set age = 20 where u.id = 2;
update test.`user` u set age = 20 where u.id = 3;
UPDATE test.prov_info SET name='小环岛', code='K002' WHERE id=22;
UPDATE test.prov_info SET name='中岛', code='K003' WHERE id=23;
结果:
user表id=2的数据没有阻塞,id=3的数据阻塞,是锁行
prov_info表id=22的数据没有阻塞,id=23的数据阻塞,是锁行
结论
如果查询条件命中了索引/主键,那么select … for update就会进行行锁。
如果是普通字段(没有索引/主键),那么select … for update就会进行锁表。
对于关联表的情况:
如果关联条件用到索引,那么关联表就会进行锁行
如果关联条件没有用到索引,那么关联表也会进行锁行
锁行只是跟另外一个关联相关联的行
参考
https://blog.51cto.com/javastack/4635681
select .... for update究竟锁表还是锁行?相关推荐
- 面试官问:select......for update会锁表还是锁行?
欢迎关注方志朋的博客,回复"666"获面试宝典 select查询语句是不会加锁的,但是select .......for update除了有查询的作用外,还会加锁呢,而且它是悲观锁 ...
- select....for update会锁表还是锁行
select -for update 除了有查询的作用外,还会加锁呢,而且它是悲观锁.那它会加表锁还是行锁?相信很多人都知道这个结论:要看是不是用了索引/主键.没用索引/主键的话就是表锁,否则就是是行 ...
- select......for update会锁表还是锁行。
select查询语句是不会加锁的,但是select .......for update除了有查询的作用外,还会加锁呢,而且它是悲观锁. 那么它加的是行锁还是表锁,这就要看是不是用了索引/主键. 没用索 ...
- select……for update会锁表还是锁行
结果: 如果查询条件用了索引/主键,那么select - for update就会进行行锁. 如果是普通字段(没有索引/主键),那么select - for update就会进行锁表. 例如: 行锁例 ...
- select......for update会锁表还是锁行
select查询语句是不会加锁的,但是 select -for update 除了有查询的作用外,还会加锁呢,而且它是悲观锁. 那么它加的是行锁还是表锁,这就要看是不是用了索引/主键.没用索引/主键的 ...
- select......for update会锁表还是锁行?
select查询语句是不会加锁的,但是select .......for update除了有查询的作用外,还会加锁呢,而且它是悲观锁. 那么它加的是行锁还是表锁,这就要看是不是用了索引/主键. 没用索 ...
- oracle update 锁表还是锁行,for update造成的Oracle锁表与解锁
我遇到的情况: 当使用select语句查询表时,后面跟着for update , select * from table for update 当修改表中数据,但是没有commit就关掉PL/SQL, ...
- Oracle锁表 行级锁 表级锁 行级锁
2019独角兽企业重金招聘Python工程师标准>>> Oracle锁表 行级锁 表级锁 ---- 行被排他锁定 ----在某行的锁被释放之前,其他用户不能修改此行 ...
- mysql行级锁 表级锁 页级锁详细介绍_MySQL行级锁、表级锁、页级锁详细介绍
页级:引擎 BDB. 表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行 行级:引擎 INNODB , 单独的一行记录加锁 表级,直接锁定整张表,在你锁定期间,其它进程无法对该表进行写 ...
最新文章
- ProLiant 服务器安装 Ret Hat Enterprise Linux AS 3 说明 (一)
- MyBatis知多少(6)表现层与业务逻辑层
- dubbo mysql_dubbo系列(四) 凑一下热闹 使用dubbo redis mybatis mysql 实现商品秒杀功能...
- 13-一对多左连接查询分步查询(查询所有客户及客户对应的订单)
- 5、URLConnection(2)
- (转)Python3异常-AttributeError: module 'sys' has no attribute 'setdefaultencoding
- 【Qt串口调试助手】1.3 - 重写ComboBox下拉框的鼠标点击事件,实现点击下拉框扫描可用串口
- 每日codewars题之判断一个数是否是水仙花数
- python中如何创建一个空列表_Python创建空列表的字典2种方法详解
- Socket TCP UDP
- LayaBox1.7.16 TiledMap 销毁的问题,TiledMap销毁后屏幕变灰,不能显示
- h2ouve下载 insyde_一种基于InsydeBIOS的BIOS更改方法及系统与流程
- 如何占用计算机大量内存,windows7内存占用率高如何处理_win7电脑内存占用过高怎么办...
- 锐目对讲机的使用方法详解
- 系统集成项目管理工程师高频考点(第二章)
- Dockerfile构建镜像并发布镜像
- 9个最佳的大数据处理编程语言
- Windows 10无法调节屏幕亮度
- 第七讲:1.物联网敲击桌面打开小台灯
- svn plugin for VS —— AnkhSvn-2.6.12735下载地址