支持,但需满足mongodb 4.0+、副本集或分片集群部署、php驱动≥1.5.0;单节点不支持,事务须在显式会话中starttransaction()开启,并传入session选项执行操作,最后committransaction()或aborttransaction()。

PHP MongoDB驱动支持事务吗?
支持,但仅限于 MongoDB 4.0+ 服务端 + 副本集或分片集群(sharded cluster)部署,且 PHP 驱动版本必须 ≥ 1.5.0。单节点(standalone)部署无法开启事务——这是最常被忽略的前提,直接导致 startTransaction() 抛出 MongoDB\Driver\Exception\RuntimeException: Transaction numbers require a replica set 错误。
如何正确启动和提交一个事务?
事务必须在会话(Session)上显式开启,不能直接在 collection 上操作。典型流程是:获取会话 → 开启事务 → 执行多个写操作 → 显式提交或中止。
- 使用
$client->startSession()获取会话对象,不要复用全局连接 - 调用
$session->startTransaction(),注意它不返回值,也不抛异常(即使失败需靠后续操作暴露) - 所有参与事务的操作(如
insertOne()、updateOne())必须传入['session' => $session]选项 - 成功后调用
$session->commitTransaction();出错时必须调用$session->abortTransaction(),否则会话可能卡住
示例片段:
$session = $client->startSession();
try {
$session->startTransaction();
$collection->insertOne(['name' => 'A'], ['session' => $session]);
$collection->updateOne(['name' => 'B'], ['$set' => ['done' => true]], ['session' => $session]);
$session->commitTransaction();
} catch (Exception $e) {
$session->abortTransaction();
throw $e;
}
事务内哪些操作不被支持?
不是所有 MongoDB 操作都能放进事务。常见限制包括:
-
createCollection()、dropCollection()、createIndex()等 DDL 操作在事务中会报错Command not supported inside a transaction - 跨数据库事务不被支持(即不能在一个事务里操作
db1.users和db2.logs) - 读操作默认使用快照隔离(snapshot),但
readConcern必须设为'majority'(驱动自动设置,无需手动) - 事务有 60 秒默认超时(
maxTimeMS不影响事务生命周期),超时后服务端自动 abort,PHP 端再调commitTransaction()会失败
为什么事务执行后数据没立刻可见?
事务提交后,其他会话是否立即看到变更,取决于它们的 readConcern 级别。默认情况下(readConcern='local'),其他会话可能读到未提交数据或旧快照。要保证强一致性,需显式设置:
- 读取端也启用会话:
$session = $client->startSession() - 并指定
['readConcern' => new MongoDB\Driver\ReadConcern('majority')] - 注意:PHP 驱动 1.13+ 支持
ReadConcern构造,旧版本需升级
否则即使事务已提交,另一个并发查询仍可能返回旧值——这不是 bug,而是 MongoDB 的可调一致性模型设计。
事务不是银弹,它带来锁竞争和延迟上升,尤其在高并发写场景下。真正需要原子跨文档修改时才启用,简单单文档更新用 $set 或 findAndModify 更轻量。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











