MySQL Транзакция в хранимой процедуре не ROLLBACK - PullRequest
0 голосов
/ 28 марта 2020

Это моя хранимая процедура:

CREATE PROCEDURE `procedureName`
(
    IN var1 VARCHAR(45),
    IN var2 VARCHAR(100),
    IN var3 VARCHAR(45),
    IN var4 DATE,
    IN someMoreVars VARCHAR(100)
)
COMMENT 'just a comment'
BEGIN
    DECLARE tempVar INT DEFAULT -1;

    DECLARE exit handler for sqlexception
      BEGIN
      SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'SQLError occured. Triggered ROLLBACK';
        -- ERROR
      ROLLBACK;
    END;

    DECLARE exit handler for sqlwarning
      BEGIN
      SIGNAL SQLSTATE '35000' SET MESSAGE_TEXT = 'SQLWarning occured. Triggered ROLLBACK';
        -- WARNING
      ROLLBACK;
    END;

    START TRANSACTION;
        INSERT INTO `schemaName`.`table1` (`column1`, `column2`, `moreColumns`)
            VALUES (var1, var2, moreVars);
        SELECT LAST_INSERT_ID() INTO tempVar;
        INSERT INTO `schemaName`.`table2` (`column1`, `column2`, `evenMoreColumns`)
            VALUES (tempVar, var3, var4);
    COMMIT;

END

Почему эта хранимая процедура не откатывается? Когда я использую параметры, которые работают для первой вставки, но выдают исключение на 2-й вставке, эта процедура не выполняется, и я получаю данные в первой таблице, но нет данных во 2-й таблице.

Я использую Движок InnoDB.

Я проверил это поведение с помощью MySQL Workbench, и так как в нем было странное поведение Autocommit, встроенное в GUI, я также протестировал его, вызвав процедуру из сценария C#.

Я также проверил, упоминается ли в документации функция LAST_INSERT_ID () как функция, которая вызывает неявную фиксацию. Но не нашли его в списке. Или эта функция вызывает другую функцию, которая вызывает неявную фиксацию? И если да, есть ли обходной путь? Мне нужно вызвать эту функцию, чтобы использовать ее ПЕРВИЧНЫЙ КЛЮЧ как ИНОСТРАННЫЙ КЛЮЧ во второй таблице. Если эта информация помогает: я также использую триггеры.

Это триггер вставки одной из таблиц (они есть почти во всех таблицах при вставке / обновлении / удалении):

CREATE DEFINER = CURRENT_USER TRIGGER `schema`.`table1_AFTER_INSERT` AFTER INSERT ON `table1` FOR EACH ROW
BEGIN
    INSERT INTO `schema`.`table1_audit` (`table1_audit_action`, `table1_audit_timestamp`, `table1_audit_user`, `table1_val1`, `table1_some_more_columns`)
    VALUES ('insert', CURRENT_TIMESTAMP(), SESSION_USER(), NEW.table1_val1, NEW.table1_some_more_columns);
END

Спасибо:)

1 Ответ

0 голосов
/ 14 апреля 2020

Просто, чтобы держать этот пост в курсе новейшей информации: я нашел решение, чтобы исправить эту ошибку самостоятельно несколько дней / недель go.

Как оказалось, проблема заключалась в том, что «ROLLBACK» должен вызываться перед «SIGNAL». Если у кого-то есть подробное объяснение, почему это так, не стесняйтесь добавлять эту информацию. Но откат после сигнализации об исключении просто невозможен. Таким образом, следующий код должен работать:

DECLARE exit handler for sqlexception
BEGIN
    -- ERROR
  ROLLBACK;
  SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'SQLError occured. Triggered ROLLBACK';
END;

И, конечно, то же самое для SQLWarning.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...