我做这个测试是为了了解mysql ndb集群是如何工作的。所以我有两个sql节点。准备我创建了下表:
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);
我创建了两个会话,每个会话在不同的节点上,我在两个节点上运行: 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
既然我没有更新同一行,为什么第二个会话会失败?
1条答案
按热度按时间zpqajqem1#
第二个事务使用完整表扫描来查找要更新的行,因为name列上没有索引。因为这是一个更新,所以在决定是否应该更新行之前,扫描会对所有行进行独占锁定。带有“cat”的行是独占锁定的,因此当完整表扫描到达该行时,它将等待该行被解锁。
如果名称列上有索引,问题就会消失。但是,使用不支持索引的条件的更新或删除必须在表中的每一行上获取独占锁。