如何在WordPress中使用MySQL事务?

17

如何在WordPress中使用MySQL事务?如果其中一个子项处于活动状态,则我想删除10个子项,总删除将回滚。


您可以在一次查询中删除它。 - sectus
确保您在事务中使用正确的MySQL引擎,您正在运行哪个版本? - halfer
2个回答

39

我从未尝试过,也没有什么特别的,只是运行类似这样的查询(在START TRANSACTION之后运行您的查询,并根据结果使用COMMITROLLBACK):

mysql_query('START TRANSACTION');
$res1 = mysql_query('query1');
$res2 = mysql_query('query2');
If ( $res1 && $res2 ) {
    mysql_query('COMMIT'); // commits all queries
} else {
    mysql_query('ROLLBACK'); // rollbacks everything
}

所以,它可以使用类似这样的东西转换为WordPress

$wpdb->query('START TRANSACTION');
$result1 = $wpdb->delete( $table, $where, $where_format = null );
$resul2 = $wpdb->delete( $table, $where, $where_format = null );
if($result1 && $result2) {
    $wpdb->query('COMMIT'); // if you come here then well done
}
else {
    $wpdb->query('ROLLBACK'); // // something went wrong, Rollback
}

你也可以像这个答案一样使用try catch(不是WordPress,但是同样的想法)。您可以在Codex中了解更多关于$wpdb查询函数(querydelete)的信息。

MySQL的默认存储引擎MyISAM不支持事务,因此不能选用。如果要使用事务,请确保所有表都定义为InnoDB。


这对我似乎不起作用。我使用START TRANSACTION开始一个事务,截断一张表,插入59行数据,然后COMMIT。但是在此期间,我可以在Navicat中打开该表,并且显示的行数少于59行,因此似乎事务对我没有起作用。有没有办法在代码中确认START TRANSACTION已成功? - Liam
2
这里的问题在于truncate有一个隐式提交:https://dev.mysql.com/doc/refman/8.0/en/truncate-table.html - Full

2

在WordPress中实现事务有点困难,因为它利用全局变量$wpdb,并因此使用单个连接到数据库,因此其副作用是:

如果您运行多个此代码实例:

$wpdb->query('START TRANSACTION');
$result1 = $wpdb->delete( $table, $where, $where_format = null );
$resul2 = $wpdb->delete( $table, $where, $where_format = null );
if($result1 && $result2) {
    $wpdb->query('COMMIT'); // if you come here then well done
}
else {
    $wpdb->query('ROLLBACK'); // // something went wrong, Rollback
}

它们可以发生冲突并引起问题。由于您只有一个连接,可能会在一个线程中启动事务,而同一事务会因为您使用了一个全局变量来利用MySQL连接而传递到另一个线程。

所以,在我看来,使用WordPress中的事务比不使用它们更加冒险。最好的解决方案是仅使用mysqli类,并在每次想要进行事务查询时创建一个新连接。

$conn = new mysqli(WORDPRESS_DB_SERVER, WORDPRESS_DB_USER, WORDPRESS_DB_PASS, WORDPRESS_DB_NAME);
$conn->query('START TRANSACTION');
$sql = "DELETE FROM $table WHERE $where"; // ESCAPE YOUR DATA!
$result = $conn->query($sql);
$res1 = $conn->query('query1');
$res2 = $conn->query('query2');
If ( $res1 && $res2 ) {
     $conn->query('COMMIT'); // commits all queries
} else {
     $conn->query('ROLLBACK'); // rollbacks everything
}

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接