2

mysql文档指出,某些语句将在事务期间导致隐式提交。例如:

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 永远不要隐式提交,而是在给出会导致隐式提交的命令时失败/回滚。

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

4

2 回答 2

1

我刚刚成功尝试的另一种 hacky 方法是通过 mysql 特定命令获取创建表 DDL

SHOW CREATE TABLE `tableName`

然后使用一些正则表达式魔法并制作一个新的 DDL 查询,该查询将基于原始表创建一个临时表,并将所有更改表更改合并到创建表中。

在我的基于 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);

编辑顺便说一下,这里有一些错误(功能)报告(多年来)。在第一个中,您可以看到一个响应(可追溯到 2006 年),其中指出:由于此行为与 oracle db 中的相同,因此这是一致的...

也许应该启动功能请求“垃圾邮件活动”以使此功能请求恢复活力!

于 2013-05-22T12:09:19.730 回答
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)

不幸的是,没有办法重命名mumble2mumble,因为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;
于 2013-04-25T18:54:20.793 回答