3
DROP FUNCTION IF EXISTS my_func;
DELIMITER ||
CREATE FUNCTION my_func(arg_id INT) RETURNS VARCHAR(200)
BEGIN
    DECLARE local_id INT;
    DECLARE local_name VARCHAR(200);
    START TRANSACTION; /* <-- this is allowed */
        SELECT      id, name
            INTO    local_id, local_name
            FROM    table
            WHERE   id = arg_id
            FOR UPDATE;
        SELECT my_other_function(local_name) INTO local_name;
        UPDATE table SET name = local_name;
    COMMIT; /* <-- this is not allowed
        and yields an "Explicit or
        implicit commit is not
        allowed..." error */
    RETURN local_name;
END||
DELIMITER ;

returnステートメントは暗黙のコミットですか?

特定の関数がトランザクションとして実行されるようにするにはどうすればよいですか?

トランザクションでラップしますか?

START TRANSACTION;
    SELECT my_func(33); /* <-- no transaction statements inside the function */
COMMIT;

関数内でトランザクションを開始してコミットしますか?

SELECT my_func(33); /* <-- contains only the START TRANSACTION line */
COMMIT;

また、この問題を調査したところ、「格納された関数のステートメントが宣言された順序で実行されることが保証されていないため、バイナリロギング(および暗黙的にレプリケーション)が不整合になる可能性がある」という情報が見つかりました。

4

1 に答える 1

2

以前にこれを使用する必要がありましたが、うまくいきました:

オプション1

SET autocommit = {0 | 1}

やりたいことを完了したら、再度有効にするか、明示的なコミットを呼び出すことができます。

オプション 2 単一の一連のステートメントに対して自動コミット モードを暗黙的に無効にするには、START TRANSACTION ステートメントを使用します。

START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;

これはmysqlのWebサイト自体から入手しました-MySQL


あなたの状況では、関数がトリックを実行する前に autocommit を false に設定すると思います (上記の説明を見ると、トランザクションを開始することは同じことです)。そうすれば、トランザクション中、関数は自動コミットしません。

于 2012-06-05T13:11:21.133 に答える