MySQL-检测和处理存储过程中的锁等待超时 问题

MySQL-检测和处理存储过程中的锁等待超时 问题,mysql,stored-procedures,error-handling,locking,Mysql,Stored Procedures,Error Handling,Locking,纯粹出于学术原因,我想知道您是否可以向mysql存储过程添加一个处理程序,如果其中一个查询被锁定(例如SELECT…for UPDATE或UPDATE)查询,该处理程序能够从锁定等待超时错误中恢复 榜样 这是假设innoDB数据库设置为ISolation levelRepeatable read,定义了一个空的users表 1.示例程序: 2.在mysql终端1中运行代码: 将显示用户的内容,但交易将保持打开状态 3.在mysql终端2中运行代码: 事务将一直运行到超时(innodb\u

纯粹出于学术原因,我想知道您是否可以向mysql存储过程添加一个处理程序,如果其中一个查询被锁定(例如
SELECT…for UPDATE
UPDATE
)查询,该处理程序能够从锁定等待超时错误中恢复


榜样 这是假设innoDB数据库设置为ISolation level
Repeatable read
,定义了一个空的
users

1.示例程序: 2.在mysql终端1中运行代码:
  • 将显示
    用户
    的内容,但交易将保持打开状态
3.在mysql终端2中运行代码:
  • 事务将一直运行到超时(innodb\u lock\u wait\u timeout的默认值为50秒)


有没有可能在
lock\u test()
过程中添加一个处理程序,这样我们就可以有@out hold“timeout”?

在花了一些时间阅读之后,我能够得到我想要的:

DROP PROCEDURE IF EXISTS `lock_test`;
DELIMITER ;;
CREATE PROCEDURE `lock_test`(OUT status_out VARCHAR(255))
    MODIFIES SQL DATA
BEGIN
    DECLARE procedure_attempts INT DEFAULT 5;
    DECLARE query_timeout INT DEFAULT FALSE;
    SET status_out := 'start';

    procedure_loop:
        REPEAT
            BEGIN
                DECLARE CONTINUE HANDLER FOR 1205
                -- Error: 1205 SQLSTATE: HY000 (ER_LOCK_WAIT_TIMEOUT)
                    BEGIN
                        SET query_timeout := TRUE;
                        SET status_out := CONCAT(status_out,'-timeout');
                    END;

                IF ( procedure_attempts < 1) THEN
                    LEAVE procedure_loop;
                END IF;

                START TRANSACTION;

                    SELECT * FROM `users` FOR UPDATE;

                    IF (query_timeout) THEN
                        SET query_timeout := FALSE;
                    ELSE
                        SET status_out := CONCAT(status_out,'-success');
                        SET procedure_attempts := 0;
                    END IF;

                COMMIT;

                SET procedure_attempts := procedure_attempts - 1;
            END;
        UNTIL FALSE END REPEAT;
    -- loop
    SET status_out := CONCAT(status_out,'-end');
END;;
DELIMITER ;
大约10秒的运行时间后,输出将是
start timeout end
(如果运行时未将超时设置为1秒,则会更长)


虽然在大多数项目中可能不太实用(或不可取),但在调试从另一个查询内部运行查询时出现的超时问题时可能会很有用-我希望这可能会在将来帮助其他人。

指令“修改SQL数据”是我庞大的过程中修复的问题,其中包含大量删除指令(在不同的桌子上)谢谢。
START TRANSACTION;
SELECT * FROM `users` FOR UPDATE;
CALL `lock_test`(@out);
SELECT @out;
DROP PROCEDURE IF EXISTS `lock_test`;
DELIMITER ;;
CREATE PROCEDURE `lock_test`(OUT status_out VARCHAR(255))
    MODIFIES SQL DATA
BEGIN
    DECLARE procedure_attempts INT DEFAULT 5;
    DECLARE query_timeout INT DEFAULT FALSE;
    SET status_out := 'start';

    procedure_loop:
        REPEAT
            BEGIN
                DECLARE CONTINUE HANDLER FOR 1205
                -- Error: 1205 SQLSTATE: HY000 (ER_LOCK_WAIT_TIMEOUT)
                    BEGIN
                        SET query_timeout := TRUE;
                        SET status_out := CONCAT(status_out,'-timeout');
                    END;

                IF ( procedure_attempts < 1) THEN
                    LEAVE procedure_loop;
                END IF;

                START TRANSACTION;

                    SELECT * FROM `users` FOR UPDATE;

                    IF (query_timeout) THEN
                        SET query_timeout := FALSE;
                    ELSE
                        SET status_out := CONCAT(status_out,'-success');
                        SET procedure_attempts := 0;
                    END IF;

                COMMIT;

                SET procedure_attempts := procedure_attempts - 1;
            END;
        UNTIL FALSE END REPEAT;
    -- loop
    SET status_out := CONCAT(status_out,'-end');
END;;
DELIMITER ;
SET @@innodb_lock_wait_timeout:=1;
CALL `lock_test`(@out);
SELECT @out;