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

什么时候可以将 mysql 默认隔离机制改为读已提交

  •  
  •   byerer · Jul 7, 2025 · 5871 views
    This topic created in 444 days ago, the information mentioned may be changed or developed.

    新业务需要在事务中使用乐观锁,在 RR 下需要回滚重试整个事务,而 rc 只需要重试某一个更新,有必要改成 rc 吗,如何判断业务在满足什么条件下可以不依赖 rr ,是不是只要不依赖可重复读就行

    10 replies  •  2025-08-26 16:50:47 +08:00
    leopod1995
        1
    leopod1995  
       Jul 7, 2025
    RR 场景相当于在一个 transaction 中可以对一条读 sql 多次调用返回一致的结果,原理就是在一个 transaction 中生成了 snapshot 。一般不用 RC 的原因就是在一个事务中会重复调用同一条 sql 。

    如果能保证一个 transaction 中没有重复 sql 的情况下,是可以替换的。
    cubecube
        2
    cubecube  
       Jul 7, 2025
    @leopod1995 根本不需要保证,随时都能改,oracle 默认是 rc ,用 oracle 的系统都好好的不是。rr 纯粹为了刷存在感。
    Dorathea
        3
    Dorathea  
       Jul 7, 2025
    你都用乐观锁了, 那 RC 会比 RR 更合适吧, 毕竟你都觉得数据大概率不会冲突了
    Georgedoe
        5
    Georgedoe  
       Jul 7, 2025
    性能有瓶颈的时候吧 , 没瓶颈改了也没啥收益
    biechuli
        6
    biechuli  
       Jul 7, 2025
    如果业务在一个事务中允许一个读出来的数据被其他事务更改,且不影响正常业务的逻辑就行。话说如果只是乐观锁,完全可以不用考虑 rr 还是 rc ,直接用 update 语句判断执行结果是不是更好。
    iseki
        7
    iseki  
       Jul 7, 2025
    你不在乎多个请求查出的数据之间存在不一致的时候
    iPisces77
        8
    iPisces77  
       Jul 8, 2025
    mysql 整体就是给 RR 设计的,其他数据库都是 RC,所以你改了也没啥影响
    byerer
        9
    byerer  
    OP
       Jul 8, 2025
    @857681664 rr 情况下,在一个事务中,重试乐观锁的时候读不到最新数据呀,得先回滚事务
    kanepan19
        10
    kanepan19  
       Aug 26, 2025
    @byerer

    // @Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)
    public void addBalanceByVersion(Long id, BigDecimal amount) {
    //乐观锁 没有 for update
    long systemTime = System.currentTimeMillis();
    boolean flag = false;
    while (System.currentTimeMillis() - systemTime < waitTime) {
    flag = updateBalanceCheckVersion(id, amount);
    if (flag) {
    break;
    }
    try {
    Thread.sleep(10);
    } catch (InterruptedException e) {
    throw new RuntimeException(e);
    }
    }
    if (!flag) {
    throw new BizException("加款超时,稍后再试");
    }

    }

    要么不用事务,要么就加上 isolation = Isolation.READ_COMMITTED
    都用事务了 老老实实的 select for update 或者 update xx set balance = balance - amount . 如果要记录流水还是 行锁。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   980 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 18:37 · PVG 02:37 · LAX 11:37 · JFK 14:37
    ♥ Do have faith in what you're doing.