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

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

  •  
  •   esolve · 2017-05-29 16:04:47 +08:00 · 5402 次点击
    这是一个创建于 2736 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

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

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

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

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

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

    感觉加锁都加的很重啊
    watzds
        6
    watzds  
       2017-05-30 02:59:08 +08:00 via Android
    @esolve 这文章也不一定对,何况上面写的读加共享锁,不顶用啊,还得 for updata 才行
    watzds
        7
    watzds  
       2017-05-30 03:03:48 +08:00 via Android
    这个文章不错的。http://hedengcheng.com/?p=771
    watzds
        8
    watzds  
       2017-05-30 03:04:28 +08:00 via Android
    watzds
        9
    watzds  
       2017-05-30 03:19:42 +08:00 via Android
    如文中所说,select 快照读,一般是不加锁的,用的是 mvcc
    ixiaohei
        10
    ixiaohei  
       2017-05-30 08:51:38 +08:00
    一个是隔离级别,一个是加锁,两码事。另外如果你想读到最新的数据(就是另外个在这个事务后面开启的事务并且提交了),你必须 for update。要不然可重复读就一直读到原来的数据。
    hujianxin
        11
    hujianxin  
       2017-05-30 10:48:12 +08:00
    楼上 @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 隔离界别包含了至少这两种。

    那现在你说,到底谁严格呢?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2679 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 15:22 · PVG 23:22 · LAX 07:22 · JFK 10:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.