先声明一条,共享锁和排它锁都是放在select语句后的(除了select语句,其他语句会自动加"排它锁")。明确了这个之后我们后面挨个举例子,希望可以一起来操作,才能加深mysql锁的理解。
配置环境:
1、添加表:test,并添加一条数据
CREATE TABLE `test` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT,
`NAME` varchar(50) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
INSERT INTO `test` (`ID`, `NAME`) VALUES (NULL, 'AAA');
2、开启cmd窗口链接本地数据库的test表。切记:使用cmd,不要用sqlyog等工具(可能会自动提交事务)。
1、共享锁(lock in share mode)
1、允许其他事务同时使用共享锁
窗口1:
执行以下语句,开启事务但不执行commit;提交事务,所以相当于此条记录未结束
start transaction; -- 开启事务
select * from test where id = 1 lock in share mode; -- 添加共享锁查询id为1的记录
窗口2:
再次查询该条记录,发现是可以正常查询的,也就表明允许其他事务同时使用共享锁。
start transaction; -- 开启事务
select * from test where id = 1 lock in share mode; -- 添加共享锁查询id为1的记录
2、不允许其他事务开始排它锁
窗口3:
添加排它锁,发现不能正常执行下去,窗口1和2的事务commit后才可以正常执行,表明共享锁不能使用排它锁
start transaction; -- 开启事务
select * from test where id = 1 for update; -- 添加排它锁
3、不允许其他事务修改该行
窗口4:
修改该条记录,发现执行不下去, 表明不允许其他事务修改该行
update test set name=111 where id=1;
2、排它锁(for update)
不允许排它锁,共享锁,修改语句进行对改行进行操作
窗口1:
start transaction; -- 开启事务
select * from test where id = 1 for update; -- 添加排他锁查询id为1的记录
窗口2:
使用共享锁,发现不能正常运行
start transaction; -- 开启事务
-- 以下三条都不能正常执行
select * from test where id = 1 lock in share mode; -- 添加共享锁查询id为1的记录
select * from test where id = 1 for update; -- 添加排它锁
update test set name=111 where id=1;