V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
lsrnb
V2EX  ›  MySQL

关于在多台服务器对同一张表进行查询的过程中中遇到的错误

  •  
  •   lsrnb · 2023-01-18 18:14:12 +08:00 · 1995 次点击
    这是一个创建于 698 天前的主题,其中的信息可能已经有所发展或是发生改变。

    pS3fiZt.png 我遇到了这样的错误,我尝试 baidu/google,但是没有解决方法.
    V 友们,我应该如何解决他?

    9 条回复    2023-01-19 14:48:56 +08:00
    suke119
        1
    suke119  
       2023-01-18 18:26:59 +08:00 via iPhone
    。。。。常见的乐观锁不就搞定了
    seers
        2
    seers  
       2023-01-18 18:35:17 +08:00
    分布式锁
    yaodao
        3
    yaodao  
       2023-01-18 19:41:07 +08:00 via iPhone
    如果并发量不大,可以用简单的 redis 分布式锁或者数据库的乐观锁
    lsrnb
        4
    lsrnb  
    OP
       2023-01-18 21:08:39 +08:00
    @suke119 乐观锁是修改 version 吗?第一次修改是 0,第二次修改是 1 这样吗?
    update `user` set stau = 100001, version = 1 where stau = 100000 and version = 0;
    这样的我测试了不行,因为第一台服务器修改的结果还没传到数据库 version 还是=0,第二台服务器执行还是返回跟第一台相同的结果
    suke119
        5
    suke119  
       2023-01-18 21:23:31 +08:00 via iPhone
    @lsrnb 所以问题出在你的理解上啊,任何客户端都可以修改,你无法控制客户端的行为,你能做的只有保证谁入库谁为主,如果第一个因为网络有问题没有修改完成,但是此时第二个用户可以任何操作的,他有这个权利,如果他的行为 db 提交,不管是不是在上一个用户之前都是正确✅的,完成后第一个用户提交自然就因为版本不对失败
    h0099
        6
    h0099  
       2023-01-19 00:30:49 +08:00
    乐观并发控制是要求每个客户端的后续读写都得依赖于此前查询所获得的的`ROW_VERSION`
    比如事务 1`SELECT yi, ver FROM t`获得`(a,0)`
    那么事务 1 后续的所有对该行的读写( SELECT/UPDATE )都得依赖于`ver=0`这个此前获得的事实
    也就是对于读:事务 1 期望重新`SELECT yi, ver FROM t`获得的还是`(a,0)`,这叫做`REPEATABLE READ`(避免了幻读`phantom read`),注意 mysql 默认的事务隔离级别就是`REPEATABLE READ`所以默认是已经保证了在同一事务内不断重新执行`SELECT yi, ver FROM t`返回的永远都是`(a,0)`
    对于写:事务 1 期望`UPDATE t SET 某个其他字段 = 某值 WHERE yi = a AND ver = 0`所返回的`affected rows`是 1 行,而如果不是 1 行而是 0 行就意味着表 t 中已经不存在符合约束`WHERE yi = a AND ver = 0`的行,也就是说行`yi=a`已经被其他事务修改了

    建议参考以某企业级 orm EFCore 为背景的 MSDN 微软谜语: https://learn.microsoft.com/en-us/ef/core/saving/concurrency
    以及我之前对于类似的场景(但是是 INSERT-only 而不是 UPDATE )使用了数据库层提供的悲观并发控制,毕竟在 SQL 末尾加`FOR UPDATE`可比在 mysql 里用 TRIGGER 模拟单调递增的自增 sql server 的 ROW_VERSION 类型然后在程序业务逻辑里写乐观控制所带来的一大堆 if 简单多了: https://www.v2ex.com/t/908047
    dog82
        7
    dog82  
       2023-01-19 08:39:47 +08:00
    认识到这个问题所在并能想办法解决,就晋级成中级码农了
    Freeego
        8
    Freeego  
       2023-01-19 10:57:58 +08:00
    这个需求有点奇怪,意思是前端只处理一次数据?这样的话在后端加个分布式锁,在查询命令的时候加锁,字段 yi 修改到 1 之后再解锁。
    matepi
        9
    matepi  
       2023-01-19 14:48:56 +08:00
    除了前面各位讲到的锁方式

    其实在非强联机场景下可以用任务队列的方式,也会有很多的好处
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5393 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 46ms · UTC 03:03 · PVG 11:03 · LAX 19:03 · JFK 22:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.