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永远不要隐式提交,而是如果给出了一个会导致隐式提交的命令而失败/回滚。
我怀疑没有办法做到这一点,环顾四周,但我希望我错了。希望有人在这里知道:)
答案 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;