V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐工具
RoboMongo
推荐书目
50 Tips and Tricks for MongoDB Developers
Related Blogs
Snail in a Turtleneck
JasonLaw
V2EX  ›  MongoDB

你们是怎么处理 MongoDB 的 WriteConflict 的?

  •  
  •   JasonLaw · 2021-04-07 13:58:23 +08:00 · 2028 次点击
    这是一个创建于 1355 天前的主题,其中的信息可能已经有所发展或是发生改变。

    javascript - A lot of WriteConflict errors with MongoDB transactions - Stack Overflow中所示,假设一个事务所做的操作是“read-modify-write”,那么在多线程的环境下会出现 WriteConflict 。它介绍了两种解决方案,一种是排队系统,另一种是重新运行系统。个人觉得重新运行系统是不适合在竞争激烈的情况下使用的,那样只能让情况变得更糟。想问一下大家是怎么处理 MongoDB 的 WriteConflict 的?

    额外阅读

    12 条回复    2022-04-09 15:29:57 +08:00
    guyeu
        1
    guyeu  
       2021-04-07 20:19:08 +08:00
    避免 WriteConflict ?
    JasonLaw
        2
    JasonLaw  
    OP
       2021-04-07 21:00:09 +08:00 via iPhone
    @guyeu #1 排队系统其实就是避免的一种方法,而重新运行系统更像是“在避免不了或者不避免的情况下,应该怎么做”。但是在竞争激烈的环境下,重新运行系统真的是种好的解决方案吗?
    Nillouise
        3
    Nillouise  
       2021-04-08 10:38:56 +08:00
    跟 arp 解决冲突思路那样,重新运行系统需要等待一个随机时间,怎么样?
    guyeu
        4
    guyeu  
       2021-04-08 10:52:21 +08:00
    @JasonLaw #2 重新运行有一个缺陷,无法预期事务执行的顺序,所以我更倾向于在业务层面进行设计,采用一些手段(包括不仅限于分布式锁)避免数据库层面的写冲突。
    JasonLaw
        5
    JasonLaw  
    OP
       2021-04-08 11:23:37 +08:00 via iPhone
    @guyeu #4 “ 重新运行有一个缺陷,无法预期事务执行的顺序”是什么意思?可以举个例子解释一下吗?
    guyeu
        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.
    JasonLaw
        7
    JasonLaw  
    OP
       2021-04-08 15:29:52 +08:00
    @guyeu #6 其实“请求被服务的顺序是不确定的”会更加准确一点。

    > results in requests being serviced in a non-deterministic order.
    Liuwilliam1
        8
    Liuwilliam1  
       2022-04-08 21:36:43 +08:00
    @JasonLaw 老哥,我今天也遇到这个问题,请问怎么具体怎么解决呢,修改那个锁等待时间真的有用吗
    JasonLaw
        9
    JasonLaw  
    OP
       2022-04-08 23:09:50 +08:00
    @Liuwilliam1 #8 你的提问是这个吗? https://www.v2ex.com/t/845805

    你能提供一下具体能够复现的代码吗?
    Liuwilliam1
        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)

    我有四个事务,同时修改某一条记录的不同字段
    JasonLaw
        11
    JasonLaw  
    OP
       2022-04-09 12:21:48 +08:00
    @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”。
    Liuwilliam1
        12
    Liuwilliam1  
       2022-04-09 15:29:57 +08:00
    好的,感谢大佬了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   879 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 20:39 · PVG 04:39 · LAX 12:39 · JFK 15:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.