Mysql 集群锁定所有行
Mysql cluster locking all rows
我做这个测试是为了了解 Mysql NDB 集群是如何工作的。所以我有两个 sql 节点。
准备工作 我创建了以下 table:
CREATE TABLE tb_id (
id bigint(20) NOT NULL AUTO_INCREMENT,
ix bigint(20) default 0,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
INSERT INTO tb_id (name, ix) VALUES
('dog', 1),('cat', 2),('penguin', 3), ('cow', 4),('tiger', 5),('fish', 6);
我创建了 2 个会话,每个会话都在不同的节点上,我在两个节点上都 运行:set session autocommit=off;
然后在第一个会话上我 运行:
UPDATE tb_id SET ix = 2 where name="cat";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
不提交并且 运行 在会话 2 中提交以下内容:
UPDATE tb_id SET ix = 2 where name="fish";
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
为什么第二个会话失败,因为我没有更新同一行?
第二个事务正在使用完整 table 扫描来查找行
进行更新,因为名称列上没有索引。因为这是
一次更新,扫描之前对所有行进行独占锁定
决定是否应该更新该行。 "cat" 的行被锁定
独占,所以当完整的 table 扫描到达这一行时,它将
等待行解锁。
如果您在名称列上有索引,问题就会消失。
但是使用条件的更新或删除
没有索引支持将必须获得独占锁
table.
中的每一行
我做这个测试是为了了解 Mysql NDB 集群是如何工作的。所以我有两个 sql 节点。 准备工作 我创建了以下 table:
CREATE TABLE tb_id (
id bigint(20) NOT NULL AUTO_INCREMENT,
ix bigint(20) default 0,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
INSERT INTO tb_id (name, ix) VALUES
('dog', 1),('cat', 2),('penguin', 3), ('cow', 4),('tiger', 5),('fish', 6);
我创建了 2 个会话,每个会话都在不同的节点上,我在两个节点上都 运行:set session autocommit=off;
然后在第一个会话上我 运行:
UPDATE tb_id SET ix = 2 where name="cat";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
不提交并且 运行 在会话 2 中提交以下内容:
UPDATE tb_id SET ix = 2 where name="fish";
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
为什么第二个会话失败,因为我没有更新同一行?
第二个事务正在使用完整 table 扫描来查找行 进行更新,因为名称列上没有索引。因为这是 一次更新,扫描之前对所有行进行独占锁定 决定是否应该更新该行。 "cat" 的行被锁定 独占,所以当完整的 table 扫描到达这一行时,它将 等待行解锁。
如果您在名称列上有索引,问题就会消失。 但是使用条件的更新或删除 没有索引支持将必须获得独占锁 table.
中的每一行