MySQL InnoDB - 对交易感到困惑

Bre*_*ett 2 php mysql innodb transactions

我已经使用MySQL多年,但没有很多使用InnoDB引擎的经验.

我现在正在对它进行一些测试,因为我将要使用它并且根据我已经阅读的内容,如果THAT事务中的任何查询存在任何问题,则不应该允许任何"经历".

我的问题是,为什么,在下面的代码....当第三个查询显然有问题时,它仍然将前两个查询输入数据库吗?

$query = "BEGIN";
mysql_query($query);

$query = "INSERT INTO list_columns(lid,column_name) VALUES(8,'test')";
mysql_query($query);

$query = "INSERT INTO list_columns(lid,column_name) VALUES(8,'test')";
mysql_query($query);

$query = "INSERT INT list_columns(lid,column_name) VALUES(8,'test')";
mysql_query($query);

$query = "COMMIT";
mysql_query($query);
Run Code Online (Sandbox Code Playgroud)

编辑:我理解使用ROLLBACK&all .....但我认为交易的全部目的是如果交易中的任何查询都有任何问题,那么它们中的任何一个都将被执行......或者这只是在一个查询中有多个插入的情况,例如....如果其中一个插入存在问题,那么将不会插入任何插入?

Kon*_*rak 10

如果问题类似于" 此插入违反了唯一键 ",则将进行提交.您必须检查自己查询是否返回错误,如果是,ROLLBACK.

如果问题是例如意外关闭服务器,则不会发生查询1和2.

当然,由于你在这里的3个查询是相同的,这是一个愚蠢的例子.至少改变了lid看.你为什么不做快速测试?

编辑:您编辑了有关交易目的的问题.

事务的目的确实是使数据库保持一致状态(在ACID上阅读),但程序员需要决定什么是一致的.看看prodigitalson的答案,看看一个可能的错误捕获的php方式的例子,为你做这件事.但是当您处于事务中时,其他进程将看不到您的事务所做的更改 - 因此是原子的和孤立的.

CREATE TABLE `testkeys` (
  `lid` INT,
  `column_name` VARCHAR(50),
  UNIQUE KEY `testuniq` (`lid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

BEGIN;
INSERT INTO testkeys(lid,column_name) VALUES(1,'test 1');
INSERT INTO testkeys(lid,column_name) VALUES(2,'test 2');
INSERT INTO testkeys(lid,column_name) VALUES(3,'test 3');
INSERT INTO testkeys(lid,column_name) VALUES(2,'test 2b');
COMMIT;
Run Code Online (Sandbox Code Playgroud)


pro*_*son 7

添加Konerak所说的...这是一个简化的过程,使用PDO而不是mysql例如:

$pdo = new PDO($mysqldsn, $user, $pass);
$pdo->beginTransaction();

try {

  $pdo->query("INSERT INTO list_columns(lid,column_name) VALUES(8,'test')");
  $pdo->query("INSERT INTO list_columns(lid,column_name) VALUES(8,'test')");
  $pdo->query("INSERT INT list_columns(lid,column_name) VALUES(8,'test')");
  $pdo->commit();

} catch (PDOException $e) {

  $pdo->rollBack();
  throw $e;
}
Run Code Online (Sandbox Code Playgroud)