repeatable read 感觉比 select for update 的加锁级别还高啊
1
WangYanjie 2017-05-29 18:09:36 +08:00
直觉是两回事,想讲确又不敢保证对错,有点尴尬,姑且听听吧。
RR 只是说当前事物内的读结果都是一致,即使两次读之间有另外一个事物修改了数据并且提交。 select for update 是给相关数据加行锁,其它数据不能修改该数据。 See 别人的博客: http://hedengcheng.com/?p=771#_Toc374698312 |
2
esolve OP @WangYanjie
PR 也是通过加锁实现的,而且加锁比 select for update 感觉更甚啊 |
3
hujianxin 2017-05-29 22:55:02 +08:00
这是两个概念,PR 是事务隔离级别,而 select for update 是对数据枷锁。
如果非要强行对比的话,你可以这样理解,如果一个引擎事务隔离级别是 PR,读取同一条数据,多个事务是可以同时读取的,而且是可重复读取。但是加了排它锁之后,这条数据一次只能被一个事务读取。 PR 不是单纯的通过锁来实现的,在 InnoDB 中,有一个功能叫 MVCC (多版本并发控制),在多个事务并发读取一行数据的时候,并没有加锁,而是通过这么类似一个乐观锁的 MVCC 机制来实现,MVCC 机制的关键在于,他为每一行数据添加了两个隐藏字段,用来代表这行数据的新建版本和删除版本,具体可以查阅相关文档。 所以说,如果非要让他们比较的话,select for update 更严格。 |
4
esolve OP @hujianxin 在具体实践的时候,也就是具体用的时候,如何注意这些啊,如何在设置了事务隔离级别的情况下,慎重的用锁啊?知道哪些锁不必要再设置?
|
5
esolve OP @hujianxin
http://blog.csdn.net/gaoshan_820822/article/details/4582561 你看这篇文章 1 脏读:修改时加排他锁,直到事务提交后才释放,读取时加共享锁,读取完释放事务 1 读取数据时加上共享锁后(这 样在事务 1 读取数据的过程中,其他事务就不会修改该数据),不允许任何事物操作该数据,只能读取,之后 1 如果有更新操作,那么会转换为排他锁,其他事务更 无权参与进来读写,这样就防止了脏读问题。 但是当事务 1 读取数据过程中,有可能其他事务也读取了该数据,读取完毕后共享锁释放,此时事务 1 修改数据,修改 完毕提交事务,其他事务再次读取数据时候发现数据不一致,就会出现不可重复读问题,所以这样不能够避免不可重复读问题。 2 不可重复读:读取数据时加共享锁,写数据时加排他锁,都是事务提交才释放锁。读取时候不允许其他事物修改该数据,不管数据在事务过程中读取多少次,数据都是一致的,避免了不可重复读问题 3 幻读问题:采用的是范围锁 RangeS RangeS_S 模式,锁定检索范围为只读,这样就避免了幻影读问题,在这里有个描述范围锁的文章 ----------------------------------- 感觉加锁都加的很重啊 |
7
watzds 2017-05-30 03:03:48 +08:00 via Android
这个文章不错的。http://hedengcheng.com/?p=771
|
8
watzds 2017-05-30 03:04:28 +08:00 via Android
|
9
watzds 2017-05-30 03:19:42 +08:00 via Android
如文中所说,select 快照读,一般是不加锁的,用的是 mvcc
|
10
ixiaohei 2017-05-30 08:51:38 +08:00
一个是隔离级别,一个是加锁,两码事。另外如果你想读到最新的数据(就是另外个在这个事务后面开启的事务并且提交了),你必须 for update。要不然可重复读就一直读到原来的数据。
|
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 隔离界别包含了至少这两种。 那现在你说,到底谁严格呢? |