===============
1 准备数据
1.1 建表
DROP TABLE IF EXISTS employee;
CREATE TABLE IF NOT EXISTS employee (
id INT PRIMARY KEY auto_increment,
name VARCHAR(40),
money INT
)ENGINE INNODB;
注意:ENGINE 是 INNODB(因为 InnoDB 才支持行锁)
1.2 插入数据
INSERT INTO employee(name, money) VALUES('Alice', 10000);
INSERT INTO employee(name, money) VALUES('Bob', 10000);
2 测试
2.1 测试前准备
- 准备两个会话(终端、命令行),一个白色的(记为:左),一个黑色的(记为:右)
- 两个会话均设置 autocommit = 0
命令如下:
SET autocommit = 0;
在左侧会话中执行的结果:
在右侧会话中执行的结果:
2.2 更新不同行
2.2.1 测试
第一步:在左侧会话中执行
UPDATE employee SET money = money + 10000 WHERE id = 1;
第二步:在右侧会话中执行
UPDATE employee SET money = money + 5000 WHERE id = 2;
可以看到,左右两个会话可以同时分别执行,不会相互产生影响。
第三步:两个终端都提交
第四步:两个终端分别查询
SELECT * FROM employee;
结果是,两个终端查询的结果相同,且这两条数据库记录分别是被这两个终端更新后的结果(10000+10000=20000,10000+5000=15000)。
2.2.2 结论
对于 InnoDB 默认的行锁来说,如果更新不同的行,它们可以同时操作、不会相互影响。
2.3 更新同一行
2.3.1 测试
第一步:在左侧会话中执行
UPDATE employee SET money = money + 10000 WHERE id = 1;
第二步:在右侧会话中执行
UPDATE employee SET money = money - 1000 WHERE id = 1;
可以看到,Sql语句被挂起(阻塞)!
第三步:左侧执行COMMIT(注意看右侧会话中Sql语句执行的变化)
第四步:注意右侧会话
第五步:右侧执行COMMIT
第六步:查看左侧结果
第七步:查看右侧结果
可以看到,左右两侧结果相同,且正确(20000+10000=30000-1000=29000)
2.3.2 结论
InnoDB 行锁,当更新同一行时,在前一个会话未提交之前,后一个会话的更新操作会被阻塞(挂起),直到前一个会话提交后,后一个更新操作才能得以执行。
3 结论
InnoDB 行锁,当更新不同行时不会相互影响,只有更新同一行时才会产生阻塞。