2017-12-22 14 views
1

私は1スケジューラで2つのクエリを持っています。SCHEDULEステートメントでトランザクションを使用するにはどうすればよいですか?

サンプル:

CREATE EVENT worker 
ON SCHEDULE EVERY 1 DAY STARTS '2017-12-22 00:00:00' 
DO 

INSERT INTO tbl1 (column) values ('foo') 
UPDATE tbl2 SET column = 'foo' 

私はMYSQLでこのスケジューラでトランザクションを使用したいです。

たとえば、更新クエリのエラーが表示された場合、挿入クエリをロールバックします。どうやってやるの ?

反応のThx。

+0

「START TRANSACTION;」と「COMMIT;」だけを使用してください。ここで 'ROLLBACK'を使う必要はありません。 –

+0

@PaulSpiegelあなたのコメントを答えとして書いてください、私の男、そしておそらくそれらのステートメントがスクリプトに入る場所を示してください –

答えて

1

START TRANSACTION;COMMIT;の間に文を入れてください。トランザクション内のステートメントのいずれかがエラーで失敗すると、COMMITコマンドは実行されません。したがって、変更は永続化されず、明示的にロールバックする必要はありません。

あなたは以下のスクリプトでそれをテストすることができます。

DROP TABLE IF EXISTS `tbl1`; 
CREATE TABLE IF NOT EXISTS `tbl1` (
    `column` varchar(50) COLLATE utf8_unicode_ci NOT NULL, 
    `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP 
) ENGINE=InnoDB; 

DROP TABLE IF EXISTS `tbl2`; 
CREATE TABLE IF NOT EXISTS `tbl2` (
    `column` VARCHAR(50) NOT NULL COLLATE 'utf8_unicode_ci', 
    `ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    UNIQUE INDEX `column` (`column`) 
) ENGINE=InnoDB; 

DROP TABLE IF EXISTS `worker_log`; 
CREATE TABLE `worker_log` (
    `ts` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP 
) ENGINE=InnoDB; 

DROP EVENT IF EXISTS `worker`; 
DELIMITER // 
CREATE DEFINER=`root`@`localhost` EVENT `worker` ON SCHEDULE EVERY 10 SECOND 
STARTS NOW() + INTERVAL 10 SECOND 
ENDS NOW() + INTERVAL 70 SECOND 
ON COMPLETION PRESERVE ENABLE DO BEGIN 
    INSERT INTO worker_log (`ts`) values (NOW()); 
    START TRANSACTION; 
     INSERT INTO tbl1 (`column`) values ('foo'); 
     INSERT INTO tbl2 (`column`) values ('foo'); 
    COMMIT; 
END// 
DELIMITER ; 

SET GLOBAL event_scheduler = ON; 

今しばらく待って、あなたのテーブルに書き込まれているものを見て:

select * from worker_log; 

ts 
------------------- 
2017-12-23 16:24:44 
2017-12-23 16:24:54 
2017-12-23 16:25:04 
2017-12-23 16:25:14 
2017-12-23 16:25:24 
2017-12-23 16:25:34 
2017-12-23 16:25:44 

あなたは、イベントがすべての実行されたことを確認10秒(定義どおり)。

select * from tbl1; 

column | ts 
-------+----------------------- 
foo | 2017-12-23 16:24:44 

select * from tbl2; 

column | ts 
-------+-------------------- 
foo | 2017-12-23 16:24:44 

しかし、ここでは、トランザクション内のステートメントは最初の実行にのみ影響することがわかります。これは、tbl2columnUNIQUEと定義されているため、最初の実行後に2番目のステートメントが失敗したためです。同じ値をこの列に挿入しようとしたためです。しかし、最初のステートメントは問題なく実行する必要がありますが(tbl1.columnUNIQUEではないため)、永続化されていません。

関連する問題