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

2017-05-29 16:04:47 +08:00
 esolve

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

5251 次点击
所在节点    MySQL
11 条回复
WangYanjie
2017-05-29 18:09:36 +08:00
直觉是两回事,想讲确又不敢保证对错,有点尴尬,姑且听听吧。

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

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

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

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

所以说,如果非要让他们比较的话,select for update 更严格。
esolve
2017-05-30 02:41:18 +08:00
@hujianxin 在具体实践的时候,也就是具体用的时候,如何注意这些啊,如何在设置了事务隔离级别的情况下,慎重的用锁啊?知道哪些锁不必要再设置?
esolve
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
2017-05-30 02:59:08 +08:00
@esolve 这文章也不一定对,何况上面写的读加共享锁,不顶用啊,还得 for updata 才行
watzds
2017-05-30 03:03:48 +08:00
这个文章不错的。http://hedengcheng.com/?p=771
watzds
2017-05-30 03:04:28 +08:00
watzds
2017-05-30 03:19:42 +08:00
如文中所说,select 快照读,一般是不加锁的,用的是 mvcc
ixiaohei
2017-05-30 08:51:38 +08:00
一个是隔离级别,一个是加锁,两码事。另外如果你想读到最新的数据(就是另外个在这个事务后面开启的事务并且提交了),你必须 for update。要不然可重复读就一直读到原来的数据。
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 隔离界别包含了至少这两种。

那现在你说,到底谁严格呢?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/364593

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX