如何防止mysql隐式提交

时间:2013-04-25 18:24:55

标签: mysql transactions

mysql documentation声明某些语句将在事务期间导致隐式提交。例如:

CREATE TABLE foo (bar INT);
START TRANSACTION;
INSERT INTO foo VALUES (1);
CREATE TEMPORARY TABLE mumble like foo;
ALTER TABLE mumble modify bar INT UNSIGNED;
ROLLBACK;
SELECT * FROM foo;
回滚后,我从foo返回一行 - 文档实际上说如果你使用临时关键字,alter table不应该导致隐式提交,但ALTER TEMPORARY TABLE是无效语法,并且丢弃临时表不会导致隐式提交,所以我怀疑只有一个错误(至少从5.5.29开始)

在任何情况下,我想要做的是告诉mysql永远不要隐式提交,而是如果给出了一个会导致隐式提交的命令而失败/回滚。

我怀疑没有办法做到这一点,环顾四周,但我希望我错了。希望有人在这里知道:)

2 个答案:

答案 0 :(得分:1)

我刚尝试的另一种hacky方法是通过mysql特定命令获取create table DDL

SHOW CREATE TABLE `tableName`

然后制作一些regexp魔术并制作一个新的DDL查询,该查询将基于原始表创建一个临时表,并将所有alter table更改合并到create table中。

在我的基于PHP的项目中,我执行了以下操作,为临时表添加唯一索引。它完成了这个技巧,并且在事务中没有发生隐式提交。

$createDDL = ... get from SHOW CREATE TABLE `tableName`
$nr = 0;
$createDDL = preg_replace("/CREATE TABLE `$tableName` \(/", "CREATE TEMPORARY TABLE `$tmpName` (\nUNIQUE `ukey-1` ($uniqCols),", $createDDL, -1, $nr);
if (!$nr)
  throw new Exception("CREATE TABLE replacement error. No reps made.");
mysqli_query($con, $createDDL);

编辑顺便说一下,这里有一些bug(功能)报告(多年以来)。在第一个中你可以看到一个响应(约会到2006年),表明:由于这种行为与oracle db中的相同,这是一致的......

可能会启动功能请求“垃圾邮件广告系列”以使此功能请求恢复!

答案 1 :(得分:0)

至少在MySQL 5.5.19中,你是对的。文档声明ALTER TEMPORARY TABLE不会进行显式提交,但MySQL会对TEMPORARY关键字进行扼杀。

我可以想到两种可能的解决方法:

解决方法1:

使用新的临时表代替ALTER

CREATE TABLE foo (bar INT);
START TRANSACTION;
INSERT INTO foo VALUES (1);
CREATE TEMPORARY TABLE mumble LIKE foo;
CREATE TEMPORARY TABLE mumble2 (bar INT UNSIGNED) SELECT * FROM mumble;
ROLLBACK;
SELECT * FROM foo;

最后一个语句产生以下输出:

Empty set (0.00 sec)

很遗憾,无法将mumble2重命名为mumble,因为临时表不允许RENAME,而ALTER mumble2 RENAME mumble隐式提交。

解决方法2:

不要使用临时表,而是生成一个子进程来运行会导致隐式提交的命令:

流程1:

CREATE TABLE foo (bar INT);
START TRANSACTION;
INSERT INTO foo VALUES (1);

进程2(并使用与MySQL的不同连接):

CREATE TABLE mumble LIKE foo;
ALTER TABLE mumble modify bar INT UNSIGNED;

流程1:

ROLLBACK;
SELECT * FROM foo;
DROP TABLE IF EXISTS mumble;