Mysql锁机制--行锁

Mysql 系列文章主页

===============

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;

在左侧会话中执行的结果:

Mysql锁机制--行锁

在右侧会话中执行的结果:

Mysql锁机制--行锁

2.2 更新不同行

2.2.1 测试

第一步:在左侧会话中执行

UPDATE employee SET money = money + 10000 WHERE id = 1;

Mysql锁机制--行锁

第二步:在右侧会话中执行

UPDATE employee SET money = money + 5000 WHERE id = 2;

Mysql锁机制--行锁

可以看到,左右两个会话可以同时分别执行,不会相互产生影响。

第三步:两个终端都提交

Mysql锁机制--行锁

Mysql锁机制--行锁

第四步:两个终端分别查询

SELECT * FROM employee; 

Mysql锁机制--行锁

Mysql锁机制--行锁

结果是,两个终端查询的结果相同,且这两条数据库记录分别是被这两个终端更新后的结果(10000+10000=20000,10000+5000=15000)。

2.2.2 结论

对于 InnoDB 默认的行锁来说,如果更新不同的行,它们可以同时操作、不会相互影响。

2.3 更新同一行

2.3.1 测试

第一步:在左侧会话中执行

UPDATE employee SET money = money + 10000 WHERE id = 1; 

Mysql锁机制--行锁

第二步:在右侧会话中执行

UPDATE employee SET money = money - 1000 WHERE id = 1;

Mysql锁机制--行锁

可以看到,Sql语句被挂起(阻塞)!

第三步:左侧执行COMMIT(注意看右侧会话中Sql语句执行的变化)

Mysql锁机制--行锁

第四步:注意右侧会话

Mysql锁机制--行锁

第五步:右侧执行COMMIT

Mysql锁机制--行锁

第六步:查看左侧结果

Mysql锁机制--行锁

第七步:查看右侧结果

Mysql锁机制--行锁

可以看到,左右两侧结果相同,且正确(20000+10000=30000-1000=29000)

2.3.2 结论

InnoDB 行锁,当更新同一行时,在前一个会话未提交之前,后一个会话的更新操作会被阻塞(挂起),直到前一个会话提交后,后一个更新操作才能得以执行。

3 结论

InnoDB 行锁,当更新不同行时不会相互影响,只有更新同一行时才会产生阻塞。

上一篇:MySQL 行锁 表锁机制


下一篇:Extjs4.2布局——Ext.container.ViewportView