重复键错误不会取消/回滚MySQL事务。

10
在MySQL InnoDB事务中,我本来希望出现重复键错误会导致回滚。但实际上并不会,相反它只是抛出一个错误,并继续执行下一条命令。一旦达到COMMIT命令,事务就会提交,但排除了导致错误的重复键命令。
这是预期行为吗?如果是,那么如何设置以便在出现此类错误时回滚而不是提交事务?
测试环境:
CREATE TABLE `test` (  
  `id` int(11) NOT NULL, 
  PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

BEGIN;
     INSERT INTO test VALUES (5);
     INSERT INTO test VALUES (5);
COMMIT;

期望结果:表格test为空。

实际结果:表格test包含一个值为5的记录。


参见:http://dev.mysql.com/doc/refman/5.0/en/innodb-error-handling.html - BlueRaja - Danny Pflughoeft
2个回答

9
如果由于重复而导致插入失败,数据库会将事务回滚到该语句的开始处。它使用在语句开头创建的内部保存点,然后回滚到该保存点。它不会回滚整个事务,因为这可能不是您想要的。mysql客户端的行为可以使用命令行参数进行配置。它可以退出(这将隐式回滚)或继续执行。如果您正在使用自己的应用程序,则由您决定其操作。mysql不会对如何处理故障施加策略 - 它将其留给您的应用程序。因此,您可以忽略它们,如果愿意的话。

2
我想给你100个声望点,用于“Mysql对于如何处理故障没有强制规定 - 它将这一切交给了你的应用程序。所以你可以自行决定如何处理它们 - 如果你愿意,你可以选择忽略它们。” - longneck
那么有没有一种方法可以设置事务,使其在出现重复键错误时自动回滚?还是我必须监视每个查询的结果,然后显式地回滚以获得这种行为? - allixsenos

3

我知道 MySql(以及其他我所知道的 SQL 引擎)在出现错误时不会自动回滚事务。

你需要声明一个错误处理程序来回滚事务:

DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING, NOT FOUND
BEGIN 
  ROLLBACK; 
  CALL ERROR_ROLLBACK_OCCURRED; 
END;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接