› 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
awanganddong
V2EX  ›  MySQL

mysql 并发操作的问题

  •  
  •   awanganddong · Dec 25, 2021 · 3926 views
    This topic created in 1740 days ago, the information mentioned may be changed or developed.

    业务场景是这样的,单一用户的账号,可能会牵扯到并发问题。 就是在同一秒内,该用户的余额会频繁更新。 首先加锁这种情况不太适合。 单纯从 mysql 自身这个问题能否解决? 或者说把金额存入内存。

    这是知乎的一个提问

    https://www.zhihu.com/question/61484424

    13 replies  •  2021-12-25 20:21:04 +08:00
    fkdog
        1
    fkdog  
       Dec 25, 2021   ❤️ 1
    单个用户频繁更新算不上并发。直接加行锁完事了。
    就算一秒钟更新 20 下,行锁都是绰绰有余。
    你觉得不合适大概率只是你自己觉得,跑一下压测就知道了,大多数情况只是杞人忧天。。
    0ZXYDDu796nVCFxq
        2
    0ZXYDDu796nVCFxq  
       Dec 25, 2021
    每次的变动还得计流水吧
    Saxton
        3
    Saxton  
       Dec 25, 2021
    “就是在同一秒内,该用户的余额会频繁更新。 首先加锁这种情况不太适合。”
    你这种情况就适合的就是行锁,为什么不太适合
    notejava
        4
    notejava  
       Dec 25, 2021
    乐观锁
    swcat
        5
    swcat  
       Dec 25, 2021
    加个版本,
    update xx_table set balance = :balance where id = :id and version_id = :version_id
    根据实际情况修改

    或者加个
    先锁住: select for update
    再判断: 这个也得判断下, 判断状态能否更新, 结果得大于 0 吧, 状态可以改吧....
    后更新: 更新数据

    id 为为主键
    mitu9527
        6
    mitu9527  
       Dec 25, 2021
    一般代码都是先读后写,所以除非你代码就是纯更新,否则先去开事务。
    搞清楚并发问题所竞争的资源到底是啥。到底是这条记录还是这条记录里面的金额。
    如果只是金额,看看能不能用 update ... set money = money + n 解决。
    如果上面的方式不行,可以考虑用悲观并发控制策略和乐观并发控制策略,也就是大家常说的悲观锁和乐观锁。选那种,取决于发生的频率和引发的后果到底有多大。
    悲观锁最简单的就是用 select for update 或者 redis 来实现,自己根据情况选,两种方式也都不是完美的,引入那种你认为合适的就可以了。
    乐观锁一般就是用版本号来实现。
    根据情况看看是否有必要做幂等判断,比如状态判断什么的。
    7911364440
        7
    7911364440  
       Dec 25, 2021
    把金额也作为更新条件呢?
    update t set money = money+n where id = :id and money = :money
    awanganddong
        8
    awanganddong  
    OP
       Dec 25, 2021
    业务场景就是用户之间赠送礼物,比如同一秒多个用户给一个用户 A 送礼物。
    如果这时候加行锁的话,用户这条记录就被锁定了。
    问题就在于用户这张数据表属于热表,该条记录的其他字段在其他业务也有更新操作。
    担心行锁的话,就会出现死锁的情况。

    更可怕的一点,我们这边是主从库配置,现在我暂时把代码切换成查主库,可以降低该概率的发生。
    现在对用户操作,都有日志记录。

    既然如此,现在我能发现问题,但是对于怎么成本最小的解决这个问题,或者优化这个问题,现在没有太大思路。
    awanganddong
        9
    awanganddong  
    OP
       Dec 25, 2021
    类似于客观锁这种机制,所带来问题就是用户操作的失败。
    这从代码层面其实没有太大问题,但是对于产品侧,用户体验方面,这个问题就比较严重。
    如果乐观锁校验失败,这个就更新失败。
    awanganddong
        10
    awanganddong  
    OP
       Dec 25, 2021
    我先压测下关于频繁更新的行锁情况吧。这个很靠谱的。
    sagaxu
        11
    sagaxu  
       Dec 25, 2021
    行锁每秒 10W 次是扛得住的,高配机器能做到 20W 次
    fiypig
        12
    fiypig  
       Dec 25, 2021 via iPhone
    行锁就可以,又不是表锁
    git00ll
        13
    git00ll  
       Dec 25, 2021
    for update 没问题的,每秒 4000 次
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   3583 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 45ms · UTC 05:26 · PVG 13:26 · LAX 22:26 · JFK 01:26
    ♥ Do have faith in what you're doing.