非关系型数据库真的不能做事务吗?
很多人在用非关系型数据库时都遇到过这个问题:我想保证数据的一致性,比如转账操作,要么都成功,要么都失败,可我用的是 MongoDB 或 Redis 这类 NoSQL,它们支持事务吗?
答案是:现在的不少非关系型数据库已经支持事务了,只是方式和传统的关系型数据库不太一样。
MongoDB 的多文档事务
以 MongoDB 为例,从 4.0 版本开始就支持了跨集合、跨文档的事务操作,适用于副本集;到了 4.2 版本,还支持了分片集群上的事务。也就是说,你现在可以在 MongoDB 中写类似这样的代码:
session.startTransaction();\ntry {\n db.accounts.updateOne({ _id: \"A\" }, { $inc: { balance: -100 } }, { session });\n db.accounts.updateOne({ _id: \"B\" }, { $inc: { balance: 100 } }, { session });\n session.commitTransaction();\n} catch (error) {\n session.abortTransaction();\n throw error;\n}这段逻辑和你在 MySQL 里写的 BEGIN + COMMIT/ROLLBACK 几乎一个套路。只要加了 session,就能保证这两个更新要么一起生效,要么全都不生效。
Redis 能不能搞事务?
再说说 Redis。它确实有 MULTI 和 EXEC 命令,看起来像事务:
MULTI\nINCR counter1\nINCR counter2\nEXEC但注意,Redis 的事务不支持回滚。哪怕中间某条命令出错了(比如对字符串执行 incr),前面的命令也不会撤销。所以它更像“批量执行”,而不是严格意义上的事务。如果你需要强一致性,得自己加逻辑处理异常情况。
Cassandra 和 DynamoDB 的取舍
像 Cassandra 这种追求高可用和分区容忍的数据库,默认走的是最终一致性路线,早期根本不支持事务。现在虽然有轻量级事务(lightweight transactions),比如用 IF NOT EXISTS 或者 CAS(Compare and Set)机制,但性能代价大,不适合高频场景。
而 DynamoDB 支持单行事务,也能开启跨行事务(TransactWriteItems / TransactGetItems),虽然限制多一点——最多 25 条操作,必须在同一分区键范围内——但在实际业务中够用了,比如电商下单扣库存加订单记录这种需求。
说到底,非关系型数据库有没有事务,不能一棍子打死。关键看你用的是哪种、版本多少、部署架构如何。以前大家选择 NoSQL 是为了性能和扩展性,愿意牺牲事务;但现在越来越多产品在往“兼顾”方向走。
如果你正在做一个用户积分变动或订单创建的功能,别急着说“我用的是 MongoDB 就没法保证一致”,先查查你当前版本支不支持会话事务。很多时候,工具其实比你以为的更强大。
","seo_title":"非关系型数据库支持事务吗?真相在这里","seo_description":"非关系型数据库如MongoDB、Redis是否支持事务?本文带你了解主流NoSQL数据库的事务能力现状与使用场景。","keywords":"非关系型数据库,事务支持,NoSQL,数据库事务,MongoDB事务,Redis事务"}