我有这样的存储过程:
DECLARE err_code CHAR(5) DEFAULT '00000';
DECLARE msg TEXT;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
err_code = RETURNED_SQLSTATE, msg = MESSAGE_TEXT;
END;
START TRANSACTION;
INSERT INTO tableA .....;
INSERT INTO tableB .....;
SELECT updateJournal(id) INTO x;
IF err_code != '00000' THEN
ROLLBACK;
INSERT INTO log (msg) VALUES (msg);
ELSE
COMMIT;
END IF;
CREATE FUNCTION updateJournal(orderId INT) return int BEGIN INSERT INTO tableC ....; UPDATE tabled ....;
RETURN 1; END
有时我收到消息错误“尝试获取锁定时发现死锁;尝试重新启动事务” 存储过程已回滚,但函数
updateJournal
仍然有效(tableC 已插入,tableD 已更新),
谁能解释为什么存储过程回滚并出现死锁错误,但存储过程内的函数仍然提交。
任何人都可以解释为什么我的存储过程出现死锁错误吗?
仅根据您提供的信息很难判断是什么原因导致了僵局。您可以尝试的是,当问题发生时,收集一些信息。 Performance_schema 中有几个地方可能包含有用的信息:data_locks 表、 data_lock_waits 表、metadata_locks 表
确保收集数据,默认情况下可能并不总是收集数据。除此之外,正如已经提到的,您应该捕获
的输出SHOW ENGINE INNODB STATUS\G
这还将包含一些有关正在发生的锁定的有用信息。
您可以使用 pt-stalk 来获取全部数据,这是 Percona Toolkit 中的一个工具,旨在运行显示数据库状态的深入数据收集。您可以从以下位置下载:
wget https://percona.com/get/pt-stalk
您可以手动触发执行:
./pt-stalk --no-stalk --iterations=1 --user=root --ask-pass
您要查看的数据在文件中:
*-ps-locks-transactions
*-transactions
*-lock-waits
*-innodbstatus1
*-innodbstatus2
并不总是会创建所有文件,这取决于数据库中的情况。默认情况下 pt-stalk 在
/var/lib/pt-stalk
中创建其数据。