如javascript - A lot of WriteConflict errors with MongoDB transactions - Stack Overflow中所示,假设一个事务所做的操作是“read-modify-write”,那么在多线程的环境下会出现 WriteConflict 。它介绍了两种解决方案,一种是排队系统,另一种是重新运行系统。个人觉得重新运行系统是不适合在竞争激烈的情况下使用的,那样只能让情况变得更糟。想问一下大家是怎么处理 MongoDB 的 WriteConflict 的?
1
guyeu 2021-04-07 20:19:08 +08:00
避免 WriteConflict ?
|
2
JasonLaw OP @guyeu #1 排队系统其实就是避免的一种方法,而重新运行系统更像是“在避免不了或者不避免的情况下,应该怎么做”。但是在竞争激烈的环境下,重新运行系统真的是种好的解决方案吗?
|
3
Nillouise 2021-04-08 10:38:56 +08:00
跟 arp 解决冲突思路那样,重新运行系统需要等待一个随机时间,怎么样?
|
4
guyeu 2021-04-08 10:52:21 +08:00
@JasonLaw #2 重新运行有一个缺陷,无法预期事务执行的顺序,所以我更倾向于在业务层面进行设计,采用一些手段(包括不仅限于分布式锁)避免数据库层面的写冲突。
|
5
JasonLaw OP @guyeu #4 “ 重新运行有一个缺陷,无法预期事务执行的顺序”是什么意思?可以举个例子解释一下吗?
|
6
guyeu 2021-04-08 13:01:09 +08:00
@JasonLaw #5 你的文章倒数第二段
> MongoDB does lock a document that is being modified by a transaction. However, other sessions that attempt to modify that document do not block. Rather, their transaction is aborted, and they are required to retry the transaction. This is potentially wasteful since other operations in the transaction will need to be re-executed, and also results in requests being serviced in a non-deterministic order. |
7
JasonLaw OP @guyeu #6 其实“请求被服务的顺序是不确定的”会更加准确一点。
> results in requests being serviced in a non-deterministic order. |
8
Liuwilliam1 2022-04-08 21:36:43 +08:00
@JasonLaw 老哥,我今天也遇到这个问题,请问怎么具体怎么解决呢,修改那个锁等待时间真的有用吗
|
9
JasonLaw OP |
10
Liuwilliam1 2022-04-09 09:43:19 +08:00
@JasonLaw
err = c.Mongo.Transaction(ctx, func(sc mongo.SessionContext) error { err = c.BeforeUpdateStatus(sc, body, model.LogStatusForTotalRank) if err != nil { return err } opts := options.Update().SetUpsert(true) query := bson.D{bson.E{Key: "_id", Value: util.CreateKeyString(body.Log.Openid, cast.ToString(body.SubArea))}} scoreIncValue := util.SumSingleLogScore(body.Log) update := bson.M{"$inc": bson.M{"score": scoreIncValue}} _, err = c.Mongo.UpdateOne(sc, util.GetMongoDbRankName(), util.CreateKeyString(model.MongoDbTableGameTotalRankPre, body.Log.TripartiteId), query, update, opts) if err != nil { return err } err = c.AfterUpdateStatus(sc, body, model.LogStatusForTotalRank) if err != nil { return err } return nil }, nil) 我有四个事务,同时修改某一条记录的不同字段 |
11
JasonLaw OP @Liuwilliam1 #10 https://www.mongodb.com/community/forums/t/recommended-way-to-handle-write-conflicts-inside-transactions/104491/3
我之前的解决方案是“Just remove the transaction and let the database resolve the writes in the order they come in”。 |
12
Liuwilliam1 2022-04-09 15:29:57 +08:00
好的,感谢大佬了
|