mysql的mysql 可重复读 幻读如何实

mysql 的不可重复读怎么演示? - 知乎19被浏览<strong class="NumberBoard-itemValue" title="分享邀请回答81 条评论分享收藏感谢收起既然MySQL中InnoDB使用MVCC,为什么REPEATABLE-READ不能消除幻读?
select时,读取创建版本号&=当前事务版本号,删除版本号为空或&当前事务版本号。也就是说读不到别得提交的事务的Insert的数据,因为事务id比当前事务大,而实际上为什么会有幻读?查了很久,没有看到合适的答案
你看的高性能mysql那本书么?我也测试过,要看下你的代码例子,如果你A事务insert提交了, B事务还是可以读取到的,如果你B在A提交之前先select一下,然后就不会读到了,一致性读 &consistent read
--- 共有 1 条评论 ---
你试试在同两个session窗中更改不同隔离级别测试,RC,RR都是乱的,RR有时候不能保证幻读,RC可重复读。set global transaction isolation level read committed或者repeatable read
Percona技术团队编写Taobao技术团队翻译的
开篇第一章就提到了ACID中的事务隔离性Isolation.
my.cnf配置:
transaction-isolation = REPEATABLE-READ
READ-UNCOMMITTED(未提交读):其他事务可以看到当前事务中没有提交的修改,会导致脏读:一个事务读到另外一个事务还没有提交的数据.
READ-COMMITTED(提交读):大多数数据库默认的隔离级别,避免了脏读,但会导致不可重复读:两次执行同样的查询,可能得到不一样的结果.
REPEATABLE-READ(可重复读,默认):实现可重复读,保证同一事务多次读取同样的记录的结果是一致的.但仍避免不了幻读,不过InnoDB用多版本并发控制MVCC解决了幻读的问题.
SERIALIZABLE(可串行化):通过强制事务串行化,避免出现幻读,简单说就是在读取的每一行数据上都加锁,所以可能会导致大量的超时和锁争用的问题,实际需要并发的场景很少使用.
所谓幻读,指的是当某个事务在读取某个范围的记录时,另外一个事务又在该范围内插入了新的记录.
当之前的事务再次读取该范围内的记录时,会产生幻行.
InnoDB的MVCC,是通过在每行记录后保存两个隐藏的列来实现的.
这两个列,一个保存了行的创建时间,一个保存了行的过期时间(或删除时间).
其内存储的并不是实际的时间值,而是系统版本号.
每开始一个新的事务,系统版本号都会自动递增.
事务开始时刻的系统版本号会作为事务的版本号,
用来和查询到的每行记录的版本号进行比较.
下面看一下在默认的REPEATABLE-READ(可重复读)事务隔离级别下,MVCC的具体操作:
--- 共有 7 条评论 ---
: 同学,关于MVCC的版本可见性规则 你可以去查查资料了解下,并不是你说的那样,然后你再用show engine innodb status 看下事务那栏的信息,它会告诉你当前活跃事务 版本的可见性。。
你这个逼装的有弹性、有深度、有湿度,水也不少,可以说是非常漂亮、滑爽。但是少了那么一丝朴实,没有给我焕然一新的感觉,如果再加入那么一丝朴实的话,这个逼就无人能挡了,我希望在国际装逼总决赛的舞台上,看到焕然一新的你,好吗?我给你YES。 --via struct
eechen 自己对很多事情不了解就开始胡说八道,还不听对方的话。以德报怨,何以报德?我们尊重他,他却只会更加猖狂,还是先教会他社会的法则吧!via MikeManilone
OSC最讨厌的人:
,同意的右下角。via Bery
http://my.oschina.net/bery/tweet/9658008
: 不是什么东西都能粗略的呀,你这代码,真要拿来用的时候,那多出来的数据会加入你后续排序和计算欧几里得距离的过程,影响性能的呀。而且这种影响是毫无意义的浪费,要是写php都像你这么浪费,谁还敢用php. --via 张亦俊
mvcc只是有版本号,具体幻不幻读得看实现。
要实现不幻读,需要加锁,影响并发性能,所以数据库在默认情况下允许幻读也是可以的。如果需要避免它,可以人工加锁select for update/lock table等
--- 共有 3 条评论 ---
http://www.postgres.cn/docs/9.3/transaction-iso.html 。在PostgreSQL里,你可以请求四种可能的事务隔离级别中的任意一种。但是在内部, 实际上只有三种独立的隔离级别,分别对应读已提交,可重复读和可串行化。如果你选择了读未提交的级别, 实际上你获得的是读已提交,并且在PostgreSQL的可重复读实现中,幻读是不可能的,
: 不过这种场景比较少,比如每增加一行,在触发器更新下统计结果。如果仅用数据库的mvcc,在统计的时候,如果有其它相关的DML,虽然确实没有幻读,但实际统计的结果是过时的,如果有其它计算需要依赖这个统计,就会造成错误。
: 这样确实能在定义上避免幻读,但是实际使用的时候,多行操作如果不阻塞其它的DML语句,可能会出现过时的结果,所以一般都手动加锁来避免数据错误。
如果当前隔离级别 没有幻读 也就不是 repeatable-read了(不符合他的定义了)
Mysql从来没有实现过 MVVC
--- 共有 14 条评论 ---
: 我不是很精通这个,就说一些我观察到的片面,oracle是可以通过undo找回以前时间节点被DML的记录,如果开启archive log,就能找回任意时间节点的,但是唯独一个例外,如果一个表被DDL过,archive就丢失了。
: oracle和mysql都不能回滚,都是隐式提交的 [抠鼻]
: 查了一下, oracle不能回滚DDL
: 查了一下,, 确实不可以, 好奇怪
: 怎么回滚? [抠鼻]
那你为什么要用mysql?
引用来自“dy810810”的评论那你为什么要用mysql?哈哈, mysql 和流感差不多, 搞web不来几次,都不行
就是因为mvcc,才有的幻读
--- 共有 3 条评论 ---
mysql可重复读隔离模式下有间隙锁,但是还是没有完全解决幻读的问题.
这篇文章讲的还不错http://blog.sina.cn/dpool/blog/s/blog_00ugs7.html?vt=4
呵呵,为嘛
可以解释清楚么?
MVCC是为了解决重复读的问题的,幻读是另外一回事了,因为每个DML操作都操作的是最新的page,而不会去更新MVCC中的undo快照去update,所以同时操作最新的page 只有锁能解决幻读问题啊。幻读其实是并发问题。而MVCC为什么能解决重复读,是因为当最新的page被某个事务锁了,那么另外一个事务在读的时候只会读之前当前可见最新的版本,并且始终读的是这个page 所以可以重复读
MVCC也可以通过一些办法解决幻影读的问题,例如select之后将读取的范围映射为一个新的数据;这样当有另外一个事务去修改前事务查询范围时候,会检查到写冲突;
对于解决幻影读实现序列读的做法,mysql好像是基于严格的2PL协议做的,oracle好像是利用上面的办法解决;
其实不用上述方法,业务上在表定义的时候规避也是可以的,即一个事务中的操作如果存在因果关系,则原因为读的操作,只读一个记录,不读多条记录。鍗氬?鍒嗙被锛

我要回帖

更多关于 mysql 可重复读 实例 的文章

 

随机推荐