go 多个 goroutine 操作 mysql 出现数据混乱 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
purplecity
V2EX    问与答

go 多个 goroutine 操作 mysql 出现数据混乱

  •  
  •   purplecity 2019-08-17 11:49:52 +08:00 2596 次点击
    这是一个创建于 2254 天前的主题,其中的信息可能已经有所发展或是发生改变。

    用的 beego 的 orm 数据库连接数 10000 innodb

    用的是一个全局单例的 orm 对象

    起 200 个进程 每秒起 1 个 goroutine 去操作数据库 每个 goroutine 去操作 5 次读和 2 次更新 即每秒有 200 个 routine 总共处理 1000 次读和 400 次写的时候 持续 60s 最后发现数据库数据混乱不对

    存在部分协程重复插入 少插入 没更新等操作 重复插入可以添加唯一索引解决 没插入和没更新怎么搞呢

    但是单个 goroutine 是没问题的

    求大佬给点建议

    9 条回复    2019-08-17 14:54:10 +08:00
    blless
        1
    blless  
       2019-08-17 12:29:20 +08:00 via Android
    业务锁啊 一个进程就本机实现一个全局业务锁。多节点就搞个分布式锁。
    Maboroshii
        2
    Maboroshii  
       2019-08-17 13:26:28 +08:00
    应该是操作有问题。
    起 200 个进程 是 起 200 个 go routine 吧? 出问题的时候是否有错误,有没有打错误日志?
    还有一个问题是你的数据来源是什么? 来源数据是否并发安全? 或者 orm 对象是否并发安全?
    hhyvs111
        3
    hhyvs111  
       2019-08-17 14:06:25 +08:00
    协程起来的时候是不是传的局部变量?还是传递的指针?如果传指针可能数据会被覆盖。
    F281M6Dh8DXpD1g2
        4
    F281M6Dh8DXpD1g2  
       2019-08-17 14:07:57 +08:00 via iPhone
    隔离级别了解一下
    keepeye
        5
    keepeye  
       2019-08-17 14:08:34 +08:00
    没有代码,无法给建议
    purplecity
        6
    purplecity  
    OP
       2019-08-17 14:36:52 +08:00
    具体程序
    ```go
    func init() {

    _ = orm.RegisterDataBase("default", "mysql",
    fmt.Sprintf("%s:%s@tcp(%s:%v)/%s?charset=utf8&allowNativePasswords=true",
    CommonConf.MysqlUserName, CommonConf.MysqlPassWord, CommonConf.MysqlIP, CommonConf.MysqlPort, CommonConf.MysqlDefaultDatabase))
    //注册模型
    orm.RegisterModel(new(AdminUsers),new(Realtrade))
    //自动创建表 参数二为是否 drop 然后创建表 参数三是否打印创建表过程
    orm.RunSyncdb("default",false,true)
    }

    var hpOrm orm.Ormer

    func getOrm() orm.Ormer {
    if hpOrm == nil { hpOrm = orm.NewOrm()
    }
    return hpOrm
    }

    func UpdateByCond(table string,cond,updateMap map[string]interface{}) {
    o := getOrm()
    qs := o.QueryTable(table)
    for key,value := range cond {
    qs = qs.Filter(key,value)
    }
    qs.Update(orm.Params(updateMap))
    }

    func GetOneRecord(table string,cond map[string]interface{},resultStruct interface{}) {
    o := getOrm()
    qs := o.QueryTable(table)
    for key,value := range cond {
    qs = qs.Filter(key,value)
    }
    qs.One(resultStruct)
    }

    func GetAllRecord(table string,cond map[string]interface{},resultStruct interface{}) {
    o := getOrm()
    qs := o.QueryTable(table)
    for key,value := range cond {
    qs = qs.Filter(key,value)
    }
    qs.All(resultStruct)
    }
    ```
    然后有个进程 A 每隔 1s 会去查库 查到了所需的 B 类型数据 有多少条就起多少个协程去用 UpdateByCond 和 GetOneRecord GetAllRecord 这些读取和更新操作。 模拟多个客户端我起了 200 个进程 这 200 个进程会在一分钟内每秒插入一条不同的 B 类型数据。所以 A 会每秒起 200 个 goroutine 去更新和读取操作。。。 比较挫。。用的是一个单利对象还没去看 beego orm 源码。。。 重复写和少写没更新都有。 别说 200 个进程了 10 个进程都会有出错。。
    purplecity
        7
    purplecity  
    OP
       2019-08-17 14:46:48 +08:00
    @hhyvs111 传的是变量没问题

    for _,x := range tidList {
    go func(m map[string]interface{}) {
    //对 m 进行操作
    }(x)
    purplecity
        8
    purplecity  
    OP
       2019-08-17 14:47:22 +08:00
    @keepeye 大佬代码在你下面一层。多谢
    purplecity
        9
    purplecity  
    OP
       2019-08-17 14:54:10 +08:00
    @Maboroshii 在下面具体说明了下 数据来源是数据库的数据是每秒都会去查库的 不过确实数据库操作的结果没打日志
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2748 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 09:14 PVG 17:14 LAX 02:14 JFK 05:14
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86