我一直很佩服使用Mongodb作为主要数据库的人。
一没事务,二没锁,要它何用
大概也就只能作用博客系统这样的地方,只要稍微复杂一点的逻辑,比如Update两个表,没有事务很有可能会产生前一个Update了,后一个失败了的尴尬局面.
以及并发下,没有锁的资源 “竞态”
最后我选择 pg
json 格式的还行。 leancloud 就是 mongodb 集群。 好处就是没结构,坏处也是没结构。哈哈。
要换个思路设计表结构
@axetroy 我的理解 Mongo update 失败的情况只有超出 Mongo 存储性能之后才会出错,一般情况下不会出错。 没有事务的这个事情可以通过逻辑层实现就是麻烦一些。 从事 Node.js 后端开发近 2 年都是 Mongo 为主的一些互联网产品,也挺好的支撑下来。
1
@axetroy 楼主对应用层理解不深,导致只能依赖数据库。
@axetroy 赞同,按条算,价值高的数据还是关系型,价值偏低的数据可以考虑mongo,价值低的数据再考虑存Hive 顺便打个广告 https://www.npmjs.com/package/block-run 可以实现mongodb的命令块按顺序执行,在很多场景下解决减少重复订单和重复用户等情况哦
并不是Update失败 ( 也有可能Update参数不正确导致失败 ),而是Update中的业务抛出错误
比如
- 更新表1
- 执行某种业务逻辑a
- 更新表2
- 执行某种业务逻辑b
- 最后更新表3
就这么一整套逻辑,假设执行到第4步的时候,抛出错误,那么整个流程是失败的.
但是遗憾的是,表1,表2已经被更新了…这就是没有事务的痛点
还有高并发下,假如要更新表1中的某条数据, 并发100次,更新字段 i, i 分别为 0, 1, 2, 3, ... 98, 99
没有锁的数据库,你猜猜,这个字段 i 最后的值是多少? 答案: 不可预测
总结:
MongoDB也就适用于论坛,博客等没有高并发冲突,业务逻辑简单的场景 或者楼上说的数据价值低的场景,比如记录用户登陆记录等…
@axetroy @zysam @zy445566 高并发场景也可以不落地到数据库,内存 redis 缓存一下。 你说表中的一个字段数字增加 可以原子 +1, 如果是更新操作肯定是安最后一次更新为准啊。也可用 kafka 队列先存进去,之后慢慢取出来更新操作,再通知用户。
另外关于事务的问题,我列举了一个转账问题 比如 A 向 B 转账 500 问题,典型的一个更新失败就完蛋的类型。 1.先冗余一个账单数据:记录 A userid,B userid,转账的金额 500 , 2.先给 A 用户原子减去 500,同时绑定数据账单 id 3.再给 b 用户原子加上 500,同时绑定数据账单 id
1 2 3 步骤每一步都可以失败。 1 失败没什么影响。 2 失败也没什么影响。 3 失败坑了啊,不过没有问题。A 少了 500 ,B 没有加上 500,这时候定时任务可以根据账单表知道 A 用户有账单id ,B 用户没有账单 id,我们就知道这里数据有问题可以回滚;实际上比这复杂,我这里提供了一个思路。
@liangtongzhuo 这么复杂的实现,有人会用在生产环境中吗,特别是涉及到金额的,你确定这不是给自己找加班的理由吗? 完全没必要是不是…
这时候定时任务可以根据账单表知道 A 用户有账单id ,B 用户没有账单 id,我们就知道这里数据有问题可以回滚。 实际上比这复杂。我这里提供了一个思路。
那不是还是需要事务 说白了,你这定时任务才是交易成功的核心关键,你这关键核心还是要在事务中进行,人家说主力其实也没太大问题,你思路里的mongo和redis和kafka不都是在给最后的事务处理打辅助?
来自酷炫的 CNodeMD
@zy445566 定时器回滚不需要事务,因为对一条数据多个字段更新是原子性的。
@liangtongzhuo
只能用作博客,我也是不认同的,mongo适用的场景还是很多的,我只是觉得没有事务,确实不是那么适合用于高价值的数据上。
还有两个账号金额为何只有一条数据?
那mongodb事务出来后,mongodb场景就通吃了,没有表结构真的太方便了
@zy445566 丢了数据要背锅、赔钱甚至公司关门的,商业数据库选oracle,mssql,db2等,开源数据库首选 pg。 数据不值钱,丢了无所谓的,啥都行。比如 mysql
@whw1988 太天真了~~
@axetroy 那不是给自己找加班理由,而是给自己甚至公司挖坑。 本来数据库已经实现并且可靠实现的功能非要自己去实现,基本都是找抽的
@waitingsong mongodb这次事务出来,就解决首要问题了:数据一致性
@whw1988 要实现事务,那么 ACID 实现必然会导致性能下降。 mysql 就是这样的,之前坑爹的是号称 innodb 支持事务了,结果仅 DML 支持事务,而 DDL 是不支持的(貌似msyql v8 终于都支持了)