对一个成熟的企业级项目来说,数据一致性的要求是至关重要的。之前我们使用 MySQL 作为项目数据库时,一般会选用 InnoDB 引擎,因为 InnoDB 引擎支持事务控制,从而能保证数据一致性。

而当我们使用 MongoDB 作为项目数据库之后,我们也不得不考虑事务控制的问题。也许有的朋友会说,MongoDB 是文档型数据库,不需要考虑多表关联的情况,但在稍大型的项目中,都难免会遇到一次需要插入或者更新多个文档的情况,所以使用事务保证数据一致性,也是至关重要的。

Laravel5 框架中,我们对 MySQL 的事务控制,可以通过以下代码就能轻松实现:

DB::beginTransaction();
try {
    //perform actions.
    DB::commit();
} catch(Exception $e) {
    DB::rollback();
}

或者

DB::transaction(function() use($data) {
       //perform actions.
});

在 Laravel5 框架中,我们使用 MongoDB 数据库时,最简单的方法就是使用 jenssegers/laravel-mongodb 这个扩展,这个扩展我在之前的博文《MongoDB通过$elemMatch查询内嵌数组文档》中也有介绍。

当我们尝试使用这个扩展做事务控制时,会报这样一个错误:

Call to a member function beginTransaction() on null

这是因为,这个扩展报没有封装这个方法,是不是很失望?

其实没有关系,我们可以再参考 MongoDB 的原生文档,你会发现有 startSession() 这样一个方法,文档参考:

https://www.php.net/manual/zh/mongodb-driver-manager.startsession.php

所以后面的问题,就变成了我们如何通过 jenssegers/laravel-mongodb 这个扩展,获取到原生的 Manager 方法实现的对象。还真有,可以使用 DB::getMongoClient() 方法获取。

所以,最后 Laravel5 中使用 MongoDB,实现事务控制的代码就是:

$session = DB::getMongoClient()->startSession();
$session->startTransaction();
try {
    //perform actions.
    $session->commitTransaction();
} catch(Exception $e) {
    $session->abortTransaction();
}

另外需要注意一点,MongoDB 4.0之前的版本,是不支持事务的,所以如果你使用的是 4.0 之前的版本,建议马上升级到 4.0 以上。

本文为 陈华 原创,欢迎转载,但请注明出处:http://www.ichenhua.cn/blog/post/35