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

Mysql 的默认事务隔离级别是:Repeatable Read,为何还要 select for update?

  •  
  •   esolve · May 29, 2017 · 6228 views
    This topic created in 3410 days ago, the information mentioned may be changed or developed.

    repeatable read 感觉比 select for update 的加锁级别还高啊

    11 replies  •  2017-05-30 10:48:12 +08:00
    WangYanjie
        1
    WangYanjie  
       May 29, 2017
    直觉是两回事,想讲确又不敢保证对错,有点尴尬,姑且听听吧。

    RR 只是说当前事物内的读结果都是一致,即使两次读之间有另外一个事物修改了数据并且提交。

    select for update 是给相关数据加行锁,其它数据不能修改该数据。

    See 别人的博客: http://hedengcheng.com/?p=771#_Toc374698312
    esolve
        2
    esolve  
    OP
       May 29, 2017
    @WangYanjie
    PR 也是通过加锁实现的,而且加锁比 select for update 感觉更甚啊
    hujianxin
        3
    hujianxin  
       May 29, 2017
    这是两个概念,PR 是事务隔离级别,而 select for update 是对数据枷锁。
    如果非要强行对比的话,你可以这样理解,如果一个引擎事务隔离级别是 PR,读取同一条数据,多个事务是可以同时读取的,而且是可重复读取。但是加了排它锁之后,这条数据一次只能被一个事务读取。

    PR 不是单纯的通过锁来实现的,在 InnoDB 中,有一个功能叫 MVCC (多版本并发控制),在多个事务并发读取一行数据的时候,并没有加锁,而是通过这么类似一个乐观锁的 MVCC 机制来实现,MVCC 机制的关键在于,他为每一行数据添加了两个隐藏字段,用来代表这行数据的新建版本和删除版本,具体可以查阅相关文档。

    所以说,如果非要让他们比较的话,select for update 更严格。
    esolve
        4
    esolve  
    OP
       May 30, 2017
    @hujianxin 在具体实践的时候,也就是具体用的时候,如何注意这些啊,如何在设置了事务隔离级别的情况下,慎重的用锁啊?知道哪些锁不必要再设置?
    esolve
        5
    esolve  
    OP
       May 30, 2017
    @hujianxin
    http://blog.csdn.net/gaoshan_820822/article/details/4582561
    你看这篇文章

    1 脏读:修改时加排他锁,直到事务提交后才释放,读取时加共享锁,读取完释放事务 1 读取数据时加上共享锁后(这 样在事务 1 读取数据的过程中,其他事务就不会修改该数据),不允许任何事物操作该数据,只能读取,之后 1 如果有更新操作,那么会转换为排他锁,其他事务更 无权参与进来读写,这样就防止了脏读问题。

    但是当事务 1 读取数据过程中,有可能其他事务也读取了该数据,读取完毕后共享锁释放,此时事务 1 修改数据,修改 完毕提交事务,其他事务再次读取数据时候发现数据不一致,就会出现不可重复读问题,所以这样不能够避免不可重复读问题。

    2 不可重复读:读取数据时加共享锁,写数据时加排他锁,都是事务提交才释放锁。读取时候不允许其他事物修改该数据,不管数据在事务过程中读取多少次,数据都是一致的,避免了不可重复读问题
    3 幻读问题:采用的是范围锁 RangeS RangeS_S 模式,锁定检索范围为只读,这样就避免了幻影读问题,在这里有个描述范围锁的文章

    -----------------------------------

    感觉加锁都加的很重啊
    watzds
        6
    watzds  
       May 30, 2017 via Android
    @esolve 这文章也不一定对,何况上面写的读加共享锁,不顶用啊,还得 for updata 才行
    watzds
        7
    watzds  
       May 30, 2017 via Android
    这个文章不错的。http://hedengcheng.com/?p=771
    watzds
        8
    watzds  
       May 30, 2017 via Android
    watzds
        9
    watzds  
       May 30, 2017 via Android
    如文中所说,select 快照读,一般是不加锁的,用的是 mvcc
    ixiaohei
        10
    ixiaohei  
       May 30, 2017
    一个是隔离级别,一个是加锁,两码事。另外如果你想读到最新的数据(就是另外个在这个事务后面开启的事务并且提交了),你必须 for update。要不然可重复读就一直读到原来的数据。
    hujianxin
        11
    hujianxin  
       May 30, 2017
    楼上 @watzds 的链接讲的很清楚了。

    我强调一下重点:

    1. 快照读包括:普通的 select 语句。
    2. 当前读:insert,update,select for update 等。
    看到了吗?这里面快照读和当前读是不一样的,插入和更新这也算当前读,普通 select 与 select for update 差别就在这呢。

    当的事务隔离级别是在 RR 时,你进行快照读,则使用 MVCC 来完成,不加独占锁,这里的锁取名为共享锁,这个时候多事务是可以同时读取同一条记录的。当年使用 select for update 当前读时,就是用了独占锁,这个时候一条记录同一时刻只能被一个事务读取。

    所以说,select for update 是一种非常严格的读取方式。而 RR 事务隔离级别包含了多种:MVCC 用来快照读、select for update 当前读。也就是说 RR 隔离界别包含了至少这两种。

    那现在你说,到底谁严格呢?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4686 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 50ms · UTC 06:55 · PVG 14:55 · LAX 23:55 · JFK 02:55
    ♥ Do have faith in what you're doing.