如何使用带有 SCHEDULE 语句的事务?
How do I use a transaction with a SCHEDULE statement?
我在 1 个调度程序中有 2 个查询。
样本:
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 中使用此调度程序的事务。
因此,例如,如果更新查询出现错误,我想回滚插入查询。我该怎么做?
感谢反应。
将您的陈述放在 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
但是在这里您看到事务中的语句只对第一个 运行 有影响。这是因为 tbl2
上的 column
被定义为 UNIQUE
,而第二个语句在第一个 运行 之后失败,因为它试图将相同的值插入到该列中。但是尽管第一个语句应该 运行 没有问题(因为 tbl1.column
不是 UNIQUE
),它也没有被持久化。
我在 1 个调度程序中有 2 个查询。
样本:
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 中使用此调度程序的事务。
因此,例如,如果更新查询出现错误,我想回滚插入查询。我该怎么做?
感谢反应。
将您的陈述放在 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
但是在这里您看到事务中的语句只对第一个 运行 有影响。这是因为 tbl2
上的 column
被定义为 UNIQUE
,而第二个语句在第一个 运行 之后失败,因为它试图将相同的值插入到该列中。但是尽管第一个语句应该 运行 没有问题(因为 tbl1.column
不是 UNIQUE
),它也没有被持久化。