我在php中有以下内容:
try {
// INSERT FETCHED LIST INTO ARCHIVE
$stmt1 = $sql->prepare('INSERT INTO hsarchive (LIST) VALUES (?)');
$stmt1->bind_param("s",$total);
$stmt1->execute();
$stmt2 = $sql->prepare('TRUNCATE TABLE highscore');
$stmt2->execute();
$sql->rollback();
$stmt1->close();
$stmt2->close();
} catch (Exception $e) {
echo "error";
$sql->rollback();
}
引擎为InnoDB,连接启动如下:
$sql = getSQLAccess();
$sql->autocommit(false);
$sql->begin_transaction();
使用gettsqlaccess返回一个connection类型的对象,其中包含user, pw等。
无论如何旋转,表都会被截断,并将列表插入到存档中。我试着切换我关闭语句的地方,正如你所看到的,我目前甚至没有提交,因为我试图弄清楚为什么回滚不起作用。
有人知道吗?
编辑:所以根据最佳答案,这将是一种方式:
try {
// INSERT FETCHED LIST INTO ARCHIVE
$stmt = $sql->prepare('INSERT INTO hsarchive (LIST) VALUES (?)');
$stmt->bind_param("s",$total);
$stmt->execute();
$stmt->close();
$stmt = $sql->prepare('DELETE FROM highscore');
$stmt->execute();
$stmt->close();
$sql->commit();
} catch (Exception $e) {
$sql->rollback();
}
事务中的DDL
既然我们已经发现没有FK约束到表highscore
-那么你的问题是由于MySQL 5.0.3以来,TRUNCATE
表语法相当于删除所有行逻辑但不物理
如果这个表没有外键约束(你的情况),MySQL将通过快速方案产生TRUNCATE
操作:它将做DROP
表+ CREATE
表。因此,虽然逻辑上删除所有行是相同的,但在如何维护操作方面,并不相同。
为什么会有这样的区别?因为MySQL在事务中不支持DDL。更准确地说,这样的操作不能回滚。对于MySQL, DDL操作将立即导致隐式提交。这就是为什么你会看到你的TRUNCATE
语句:首先,即使你没有提交,也会提交;第二,回滚对它没有影响。
如果您仍然需要回滚操作,那么,不幸的是,您将需要使用DELETE
语法而不是TRUNCATE
。不幸的是——因为,很明显,DELETE
比TRUNCATE
慢得多,因为行将被逐一处理。