【问题标题】:MySQL After Insert Trigger - MyISAM vs InnoDB插入触发器后的 MySQL - MyISAM 与 InnoDB
【发布时间】:2014-05-21 12:36:57
【问题描述】:

我试图让插入后触发器不回滚对 innodb 表的插入。 MyISAM 似乎没有这个问题。

让我举例说明:

CREATE TABLE `testTable` (
  `id` int(10) AUTO_INCREMENT,
  `data` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB; #Engine supports transactions

CREATE TABLE `dummyTable` (
  `id` int(10) AUTO_INCREMENT,
  `data` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;


DELIMITER $$
CREATE TRIGGER triggerTest AFTER INSERT ON `testTable`
FOR EACH ROW
BEGIN
  INSERT INTO dummyTable VALUES(1, 2, 3, 4); #This will throw a column count error
END;$$
DELIMITER ;


INSERT INTO testTable(data) VALUES('This insert will be rolled back');
SELECT COUNT(1) FROM testTable; # 0

如果您将 testTable 的引擎更改为 MyISAM,则原始插入不会回滚,因为(我假设)MyISAM 不支持事务。

CREATE TABLE `testTable` (
  `id` int(10) AUTO_INCREMENT,
  `data` text,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM; #Engine does NOT support transactions

CREATE TABLE `dummyTable` (
  `id` int(10) AUTO_INCREMENT,
  `data` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

DELIMITER $$
CREATE TRIGGER triggerTest AFTER INSERT ON `testTable`
FOR EACH ROW
BEGIN
  INSERT INTO dummyTable VALUES(1, 2, 3, 4); #This will throw a column count error
END;$$
DELIMITER ;

INSERT INTO testTable(data) VALUES('This insert will not be rolled back');
SELECT COUNT(1) FROM testTable; # 1

问题:如果触发器中有错误,有没有办法让 InnoDB 表的插入后触发器保留原始插入?

【问题讨论】:

  • 当然 MyISAM 不会回滚原始插入,因为它无法回滚任何内容。

标签: mysql triggers innodb myisam


【解决方案1】:

是的,不同的行为与引擎是否supports transactions or not有关:

对于事务表,语句失败应导致该语句执行的所有更改回滚。触发器失败会导致语句失败,因此触发器失败也会导致回滚。对于非事务性表,无法进行此类回滚,因此尽管语句失败,但在错误点之前执行的任何更改仍然有效。

您可以declare a CONTINUE handlerthis specific error

DELIMITER $$
CREATE TRIGGER triggerTest AFTER INSERT ON `testTable`
FOR EACH ROW
BEGIN
  DECLARE CONTINUE HANDLER
      FOR SQLSTATE '21S01' -- "Column count doesn't match value count"
      BEGIN END; -- do nothing (but continue)
  INSERT INTO dummyTable VALUES(1, 2, 3, 4);
END $$
DELIMITER ;

【讨论】:

    【解决方案2】:

    到目前为止,我同意这里所说的一切。显然非事务性存储引擎不会回滚。但是,您可以将触发器更改为 BEFORE 而不是 AFTER 触发器,并获得与 InnoDB 示例相同的结果,即未提交的更改:

    CREATE TABLE `__testTable` (
      `id` int(10) AUTO_INCREMENT,
      `data` text,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM; #Engine does NOT support transactions
    
    CREATE TABLE `dummyTable` (
      `id` int(10) AUTO_INCREMENT,
      `data` text,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB;
    
    DELIMITER $$
    CREATE TRIGGER triggerTest BEFORE INSERT ON `__testTable`
    FOR EACH ROW
    BEGIN
      INSERT INTO dummyTable VALUES(1, 2, 3, 4); #This will throw a column count error
    END;$$
    DELIMITER ;
    
    INSERT INTO __testTable(data) VALUES('This insert will not occur!');
    SELECT COUNT(1) FROM __testTable; # 1
    

    【讨论】:

      猜你喜欢
      • 2011-05-14
      • 1970-01-01
      • 2011-10-17
      • 1970-01-01
      • 2012-10-20
      • 2016-10-13
      • 1970-01-01
      • 2011-09-17
      • 2012-07-15
      相关资源
      最近更新 更多