在MySQL中,当多个事务试图同时访问同一行数据时,可能会发生锁等待。锁等待是指一个事务(T1)正在等待另一个事务(T2)释放它所需要的资源上的锁。这种情况下,T1将被挂起直到T2完成并释放了锁。
下面是一个简单的示例来展示如何在MySQL中创建锁等待的情况。我们将使用InnoDB存储引擎,因为它是唯一支持行级锁定的MySQL存储引擎之一。
准备工作
首先,确保你的数据库使用的是InnoDB存储引擎。如果需要,可以创建一个新的表:
CREATE TABLE test_lock (
id INT NOT NULL,
data VARCHAR(255),
PRIMARY KEY (id)
) ENGINE=InnoDB;
插入一些初始数据:
INSERT INTO test_lock (id, data) VALUES (1, 'Initial Data');
创建锁等待
步骤1: 开启第一个事务
打开一个MySQL命令行窗口,并开始一个事务:
START TRANSACTION;
更新表中的一行数据,这将获取该行的排他锁:
UPDATE test_lock SET data = 'Data Changed by T1' WHERE id = 1;
此时,如果你查询当前会话中的锁信息,可以看到已经获得了一行记录的锁。
步骤2: 开启第二个事务
在另一个MySQL命令行窗口中开启一个新的事务:
START TRANSACTION;
尝试更新同一行数据:
UPDATE test_lock SET data = 'Data Changed by T2' WHERE id = 1;
这时,你会注意到这个命令会暂停执行,因为它正在等待第一个事务释放锁。
步骤3: 解决锁等待
回到第一个事务所在的窗口,提交事务以释放锁:
COMMIT;
现在回到第二个事务所在的窗口,你会发现原本暂停的UPDATE
命令已经执行完毕,因为锁已经被释放。
检查锁等待情况
如果你想查看当前系统中存在的锁等待情况,可以使用以下查询:
SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread,
r.trx_query waiting_query, b.trx_id blocking_trx_id,
b.trx_mysql_thread_id blocking_thread, b.trx_query blocking_query
FROM information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx b ON w.blocking_trx_id = b.trx_id
INNER JOIN information_schema.innodb_trx r ON w.requesting_trx_id = r.trx_id;
此查询将列出所有当前存在的锁等待关系,包括哪些事务正在等待以及它们正在等待哪个事务释放锁。