概述
InnoDB 提供了两种锁定读取的模式:
- SELECT ... LOCK IN SHARE MODE
共享锁:又称“读锁”,当事务A对数据row加锁后,在提交前,其他会话可以读取,无法修改。
- SELECT ... FOR UPDATE
排它锁:又称“写锁”,当事务A对数据row加锁后,在提交前,其他会话无法读取、修改。
两种模式由InnoDB提供,需要开启事务,都属于MySQL的悲观锁。
准备
准备一张InnoDB 的用户表,并填充部分数据
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`username` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名',
`password` varchar(64) NOT NULL DEFAULT '' COMMENT '密码',
`state` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '上次修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
FOR UPDATE
事务A
在MySQL命令行终端,开启事务A,使用共享锁对id=1加锁
其他会话
在另外一个终端查询该条数据
可以看到,无论是for update 还是lock in share mode都无法读取到数据,查询被阻塞直至超时。
并且无论是否开启事务,都受到了影响
补充
只有事务A提交后,在别的会话才能得到数据
LOCK IN SHARE MODE
事务A
在MySQL命令行终端,开启事务A,使用共享锁对id=1加锁
其他会话
lock in share mode
在另外一个终端,查询该条数据lock in share mode,尝试修改
可以看到,这时候是可以获取数据的,但update被阻塞了。
for update
查询该条数据 尝试修改
可以看到,查询已经被阻塞。
参考资料:
MySQL-doc: InnoDB Locking and Transaction Model | Locking Reads