MySQL 无法在存储过程中设置事务隔离级别

时间:2021-01-19 16:58:44

标签: mysql stored-procedures transactions isolation-level

我正在使用客户端 MySQL (8.0)(来自 PyQt5)调用一个过程,该过程在表中插入记录,检索 LAST_INSERT_ID 并使用它使用 INSERT INTO TABLE SELECT 将一组记录插入另一个表中{1}} 来自临时表。

我得到了臭名昭著的

<块引用>

HY000 超出锁定等待超时;尝试重新启动事务

我通过终止主连接来避免的错误(在服务器级别手动)。我试图将隔离级别设置为限制较少的级别,但它接缝 MySQL 忽略了过程中的 SET TRANSACTION。我运行了一个测试程序(见下文),结果相同。隔离级别保持为 REPEATABLE-READ

非常欢迎任何帮助。我通过使用游标更新第二个表解决了这个问题,但我想弄清楚 SET TRANSACTON 的使用和要求。当然,我很感激关于如何避免“超出锁定等待超时”的任何其他建议

CREATE DEFINER=`root`@`localhost` PROCEDURE `test`(IN _supplierid INT)
BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
    GET DIAGNOSTICS CONDITION 1
    @p1 = RETURNED_SQLSTATE, @p2 = MESSAGE_TEXT;
    SELECT CONCAT(@p1, ' ', @p2, ' ', @@transaction_isolation);
    ROLLBACK;
    END;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
    SELECT @@transaction_isolation;
    COMMIT;
END

当我运行该过程时,结果总是“在事务级别或在 de ROLLBACK 调用之前可重复读取,这意味着隔离级别没有改变。我没有尝试在全局级别更改隔离级别,因为我不需要它。我发现一些提到“一旦你完成了所有的变量声明就可以”没有任何进一步的参考

更新:通过将 SESSION 按原样放置在存储过程上,我能够将隔离级别设置为 SESSION 级别(SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITED)。这提出了为什么以前的语法不能按照 MySQL 8.0 文档 (https://dev.mysql.com/doc/refman/8.0/en/set-transaction.html)

工作的问题

此外,我在原始存储过程中尝试了所有三个隔离级别,但都失败了,并显示“超出 HY000 锁定等待超时;尝试重新启动事务”错误。

更新二:我终于解决了我的问题,虽然我觉得问题没有得到任何回答,但我的发现可能会帮助其他面临类似问题的人。

首先,我没有提到我同时使用两个连接来连接 MySQL 服务器。一种用于常规操作,另一种用于处理临时表:常规表和临时表。当我说使用游标可以解决我的问题时,我错了。就我的两个连接都处于活动状态而言,我什至无法在某些表上运行 UPDATE 查询,即使认为所涉及的查询已经完成。我尝试使用不同的隔离级别:REPETABLE-READ; READ-COMMITED 和 READ-UNCOMMITED 具有相同的 HY000 超时结果。对我来说,这仍然是主要的悬而未决的问题。为什么没有一个隔离级别允许这样的简单情况(表格是小型测试材料)。此外,我有一个类似的设计,在系统的其他类中使用临时表和两个独立的连接,看似正常工作。剩下的另一个问题是,为什么不能在我之前的更新中提到的 TRANSACTION 级别设置隔离级别。

经过多次尝试检查服务器锁后,我终于通过仅使用一个连接解决了超时问题。使用多个可能不是最好的设计。如果有人感兴趣,我很乐意提供更多详细信息。

0 个答案:

没有答案