在 WordPress 中实现事务

WordPress 使用 wpdb 类创建的全局对象 $wpdb 实现对底层 MySQL 数据库的 DML 操作。如果你想将 WordPress 用作涉及数据库交互的开发框架,那么面临的第一个问题是 $wpdb 不支持事务,没有事务的支持,就无法保证业务的一致性。对于事务的概念这里就不做介绍了,如果你找到这篇文章,那你自然是理解的。

本插件是 wpdb 类的子类,以 wpdb 为基础实现了对事务的支持,做法是在 wpdb 类上扩展出一个子类 conn,在子类 conn 上实现对事务的支持(不受影响 wpdb 的实例 $wpdb)。为方便使用已做成插件,项目地址在这里:https://github.com/yusn/wp_conn下载地址在这里

使用方法

插件已定义了全局对象 $conn,在您的程序里只需要加入global $conn;即可通过 $conn 调用那些从 wpdb 类继承来的方法,以及 $conn 自有的一些方法。换句话说在需要时你完全可以用 $conn 来替代 $wpdb。

特性介绍

这是一个试验性的项目,仅供交流。

  • 仅支持 REST API;
  • 自动开启事务;
  • 异常自动回滚;
  • 运行结束自动提交(返回 REST API 请求时);
  • 支持多行插入;
  • 支持自动提交模式;
  • 支持手动提交;
  • 支持手动回滚;

仅支持 REST API

之所以仅仅支持 REST API,是因为开启事务/自动提交/自动回滚的实现是在 REST API 提供的 filter 上实现的(与 $wpdb 不同,$conn 默认运行在手动提交模式下)。

自动开启事务

接收到 REST API 请求时自动开启事务,无需手动开启。

运行结束自动提交

API 程序运行结束,如未有异常发生,响应返回前将自动提交事务。

异常自动回滚

当 API 程序抛出异常,或返回 WP_ERROR 类实例时,将自动执行事务回滚。
若在程序抛出异常前执行了手动提交 $conn->commit();,则提交之前的 DML 操作不会被回滚;若异常发生在手动开启事务之后,或执行$conn->commit();之后返回 WP_ERROR,则回滚仅限于手动开启事务之后的部分。

支持自动提交模式

也可以像 $wpdb 那样,让你的代码运行在自动提交模式下,只需要在程序中执行执行数据库操作前执行$conn->set_autocommit();即开启自动提交模式,此后若再发生异常或错误,则无法回滚。

支持手动提交

默认情况下(未开启自动提交)在程序执行过程中,你可以在需要时随时手动提交之前的操作,只需要执行$conn->commit();方法。执行$conn->commit();将自动开启一个新的事务,这会让你之后的代码运行在一个新事务里,这个事务在正常响应返回前会自动被提交,若后续代码发生了异常或返回 WP_ERROR 类的实例,则这部分代码会被回滚。
开启自动提交后($conn->set_autocommit();),若再执行手动提交($conn->commit();),则手动提交不会生效(也不会产生新事务),因为当前已经运行在自动提交模式下,无需手动提交。

支持手动回滚

在一个事务里,你可以随时执行$conn->rollback();方法以回滚之前的操作;若在此之前已开启了自动提交模式($conn->set_autocommit();),则回滚操作不会生效。

支持多行插入

$wpdb 的插入方法只支持单行插入,使用$conn->insert_rows();方法能够实现一次插入多行,该方法的返回结果是成功插入的总行数。

$res = $conn->insert_rows(
            'test', // 写入的表名称
            array('name'), // 写入的表字段
            array('string'), // 写入字段的字段类型
            array(
                array('aa'), // 第一行数据
                array('bb'), // 第二行数据
                array('cc'), // 第三行数据
            ),
        );

注意事项

MySQL 的 DDL 操作是无法被回滚的,即 create/drop databases,create/drop/alter table 这些命令无法被回滚,应慎重考虑在事务中包含 DDL 语句,若无法避免应考虑做相应的容错处理。

发表评论