精华内容
下载资源
问答
  • 一、什么是幻读在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读。而多出来或者少的哪一行被叫做幻行。二、为什么要解决幻读在高并发数据库系统中,需要保证事务与事务之间的隔离性,还有事务本身的...

    cf9bfdb2f4a2a21fac89b3d2078d2aa2.png

    一、什么是幻读

    在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读。而多出来或者少的哪一行被叫做幻行。

    二、为什么要解决幻读

    在高并发数据库系统中,需要保证事务与事务之间的隔离性,还有事务本身的一致性。

    三、MySQL 是如何解决幻读的

    如果你看到了这篇文章,那么我会默认你了解了脏读 、不可重复读与可重复读。

    1. 多版本并发控制(MVCC)(快照读/一致性读)

    多数数据库都实现了多版本并发控制,并且都是靠保存数据快照来实现的。以 InnoDB 为例,每一行中都冗余了两个字断。

    一个是行的创建版本,一个是行的删除(过期)版本。具体的版本号(trx_id)存在 information_schema.INNODB_TRX 表中。版本号(trx_id)随着每次事务的开启自增。

    事务每次取数据的时候都会取创建版本小于当前事务版本的数据,以及过期版本大于当前版本的数据。

    普通的 select 就是快照读。

    select * from T wherenumber=1;

    原理:将历史数据存一份快照,所以其他事务增加与删除数据,对于当前事务来说是不可见的。

    2. next-key 锁 (当前读)

    next-key 锁包含两部分:

    记录锁(行锁)

    间隙锁

    记录锁是加在索引上的锁,间隙锁是加在索引之间的。(思考:如果列上没有索引会发生什么?)

    select * from T wherenumber=1for update;

    select * from T where number=1lock in share mode;

    insert

    update

    delete

    原理:将当前数据行与上一条数据和下一条数据之间的间隙锁定,保证此范围内读取的数据是一致的。

    其他:MySQL InnoDB 引擎 RR 隔离级别是否解决了幻读

    引用一个 github 上面的评论 地址:

    Mysql官方给出的幻读解释是:只要在一个事务中,第二次select多出了row就算幻读。

    a事务先select,b事务insert确实会加一个gap锁,但是如果b事务commit,这个gap锁就会释放(释放后a事务可以随意dml操作),a事务再select出来的结果在MVCC下还和***次select一样,接着a事务不加条件地update,这个update会作用在所有行上(包括b事务新加的),a事务再次select就会出现b事务中的新行,并且这个新行已经被update修改了,实测在RR级别下确实如此。

    如果这样理解的话,Mysql的RR级别确实防不住幻读

    有道友回复 地址:

    在快照读读情况下,mysql通过mvcc来避免幻读。

    在当前读读情况下,mysql通过next-key来避免幻读。

    select * from t where a=1;属于快照读

    select * from t where a=1 lock in share mode;属于当前读

    不能把快照读和当前读得到的结果不一样这种情况认为是幻读,这是两种不同的使用。所以我认为mysql的rr级别是解决了幻读的。

    先说结论,MySQL 存储引擎 InnoDB 隔离级别 RR 解决了幻读问题。面试问烂的 MySQL 四种隔离级别,这篇文章建议大家看下。

    如引用一问题所说,T1 select 之后 update,会将 T2 中 insert 的数据一起更新,那么认为多出来一行,所以防不住幻读。看着说法无懈可击,但是其实是错误的,InnoDB 中设置了快照读和当前读两种模式,如果只有快照读,那么自然没有幻读问题,但是如果将语句提升到当前读,那么 T1 在 select 的时候需要用如下语法: select * from t for update (lock in share mode) 进入当前读,那么自然没有 T2 可以插入数据这一回事儿了。

    注意

    next-key 固然很好的解决了幻读问题,但是还是遵循一般的定律,隔离级别越高,并发越低。

    【编辑推荐】

    【责任编辑:庞桂玉 TEL:(010)68476606】

    点赞 0

    展开全文
  • 可重复概念可重复的实现Repeatable Read(可重复):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录(已经提交的,其实是早于本事务开始且已经提交的),但是不能看到其他事务对已有记录的更新...

    可重复读概念

    可重复读的实现

    Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录(读已经提交的,其实是读早于本事务开始且已经提交的),但是不能看到其他事务对已有记录的更新(即晚于本事务开始的),并且,该事务不要求与其他事务是“可串行化”的。(没有问题)

    这句话的核心,是“但是不能看到其他事务对已有记录的更新”,那么RR隔离级别是怎么保证这一点的呢?

    可重复读实现原理

    事务ID是递增的。

    使用MVCC(多版本并发控制)。InnoDB为每行记录添加了一个事务ID,每当修改数据时,将当事务ID写入。

    在读取事务开始时,系统会给事务一个当前版本号(事务ID),事务会读取版本号<=当前版本号的数据,这时就算另一个事务插入一个数据,并立马提交,新插入这条数据的版本号会比读取事务的版本号高,因此读取事务读的数据还是不会变。

    可重复读注意点

    但是,当前事务想再写这行数据的话,还是以数据库提交的数据为准。并且会加行锁,其他的事务要再来修改的话,就得等到当前事务结束。

    举例:

    我们先看看现象,再分析原理。我的mysql版本是5.5。

    下面是一张表,只有一条数据,并且我开启了事物

    此时,另一个事物将record加1,因此我在开启一个命令行客户端,执行下面的命令:

    成功加1之后,实际上,数据库中record肯定是2。

    然后回到之前的客户端,再查一次:

    没毛病,record还是1,果然是可重复读。有些人以为mysql的可重复读是通过行锁实现的,

    从上面可以知道,肯定不是,如果是的话,第一次select * from test的时候,id=1的记录就会加行锁,我都加行锁了,我还没提交,另外的事物是怎么update成功的。

    结论就是mysql使用的MVCC(多版本并发控制),MVCC详解可以看:https://blog.csdn.net/whoamiyang/article/details/51901888

    我们继续,我之前的第一个事物还没提交,不过提交之前,我也想加1;

    加完之后我再查一下,额,record是3,好像很奇怪,但也不奇怪。

    其实,update test set record=record+1 where id=1;这条语句中,在加1之前,他知道自己等于2,然后2+1=3。

    也就是说,update时读取数据是最新版本的数据,而select是到当前事物版本为止的数据。当更新成功之后,当前版本即为最新版本,再次select,读取的是最新的数据。

    在这里讨论下乐观锁的必要性。下面是乐观锁的实现,实现乐观锁,我们一般会这么做

    update test set record=record+1 where id=1 and record=1;

    如果不用乐观锁,你用select读取到的值其实根本不准确。除非你开启悲观锁,像下面这样:

    select * from test where id=1 for update;

    这样可以读取到最新的内容,同时在你当前的事物提交之前,其他事物的update此条记录将会锁等待。

    故事到此,还没有结束,此时我们开启事物三,也做加1操作看会发生什么。

    结果是,锁等待超时,也就是说(事物一)在更新完后,会加行锁,这个应该比较好理解。事物中,刚开始查询的时候是不会加行锁的,但是当有更新操作之后,会加行锁,直到事物提交。

    Innodb在RR级别如何避免幻读

    幻读定义

    事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象 发生了幻觉一样。

    mysql如何实现避免幻读

    1.在快照读读情况下,mysql通过mvcc来避免幻读。

    2.在当前读读情况下,mysql通过next-key来避免幻。

    什么是MVCC

    mvcc全称是multi version concurrent control(多版本并发控制)。mysql把每个操作都定义成一个事务,每开启一个事务,系统的事务版本号自动递增。每行记录都有两个隐藏列:创建版本号和删除版本号

    select:事务每次只能读到创建版本号小于等于此次系统版本号的记录,同时行的删除版本号不存在或者大于当前事务的版本号。

    update:插入一条新记录,并把当前系统版本号作为行记录的版本号,同时保存当前系统版本号到原有的行作为删除版本号。

    delete:把当前系统版本号作为行记录的删除版本号

    insert:把当前系统版本号作为行记录的版本号

    什么是next-key锁

    行锁+GAP间隙锁

    什么是快照读和当前读

    快照读:简单的select操作,属于快照读,不加锁。(当然,也有例外,下面会分析)

    select * from table where ?;

    当前读:特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。

    select * from table where ? lock in share mode;

    select * from table where ? for update;

    insert into table values (…);

    update table set ? where ?;

    delete from table where ?;

    展开全文
  • 可重复概念可重复的实现Repeatable Read(可重复):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录(已经提交的,其实是早于本事务开始且已经提交的),但是不能看到其他事务对已有记录的更新...

    可重复读概念

    可重复读的实现

    Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录(读已经提交的,其实是读早于本事务开始且已经提交的),但是不能看到其他事务对已有记录的更新(即晚于本事务开始的),并且,该事务不要求与其他事务是“可串行化”的。(没有问题)

    这句话的核心,是“但是不能看到其他事务对已有记录的更新”,那么RR隔离级别是怎么保证这一点的呢?

    可重复读实现原理

    事务ID是递增的。

    使用MVCC(多版本并发控制)。InnoDB为每行记录添加了一个事务ID,每当修改数据时,将当事务ID写入。

    在读取事务开始时,系统会给事务一个当前版本号(事务ID),事务会读取版本号<=当前版本号的数据,这时就算另一个事务插入一个数据,并立马提交,新插入这条数据的版本号会比读取事务的版本号高,因此读取事务读的数据还是不会变。

    可重复读注意点

    但是,当前事务想再写这行数据的话,还是以数据库提交的数据为准。并且会加行锁,其他的事务要再来修改的话,就得等到当前事务结束。

    举例:

    我们先看看现象,再分析原理。我的mysql版本是5.5。

    下面是一张表,只有一条数据,并且我开启了事物

    e3795b56ae14832985210a0f6cfa5d6a.png

    此时,另一个事物将record加1,因此我在开启一个命令行客户端,执行下面的命令:

    7727d1d38d736115f35aececceeadd75.png

    成功加1之后,实际上,数据库中record肯定是2。

    然后回到之前的客户端,再查一次:

    36e136bcd1e0d623818ff750a9a7f329.png

    没毛病,record还是1,果然是可重复读。有些人以为mysql的可重复读是通过行锁实现的,

    从上面可以知道,肯定不是,如果是的话,第一次select * from test的时候,id=1的记录就会加行锁,我都加行锁了,我还没提交,另外的事物是怎么update成功的。

    结论就是mysql使用的MVCC(多版本并发控制),MVCC详解可以看:https://blog.csdn.net/whoamiyang/article/details/51901888

    我们继续,我之前的第一个事物还没提交,不过提交之前,我也想加1;

    8598084a6465d27dd76e561d97efa178.png

    加完之后我再查一下,额,record是3,好像很奇怪,但也不奇怪。

    其实,update test set record=record+1 where id=1;这条语句中,在加1之前,他知道自己等于2,然后2+1=3。

    也就是说,update时读取数据是最新版本的数据,而select是到当前事物版本为止的数据。当更新成功之后,当前版本即为最新版本,再次select,读取的是最新的数据。

    在这里讨论下乐观锁的必要性。下面是乐观锁的实现,实现乐观锁,我们一般会这么做

    update test set record=record+1 where id=1 and record=1;

    如果不用乐观锁,你用select读取到的值其实根本不准确。除非你开启悲观锁,像下面这样:

    select * from test where id=1 for update;

    这样可以读取到最新的内容,同时在你当前的事物提交之前,其他事物的update此条记录将会锁等待。

    故事到此,还没有结束,此时我们开启事物三,也做加1操作看会发生什么。

    06762b746213f367951790927bf4b436.png

    结果是,锁等待超时,也就是说(事物一)在更新完后,会加行锁,这个应该比较好理解。事物中,刚开始查询的时候是不会加行锁的,但是当有更新操作之后,会加行锁,直到事物提交。

    Innodb在RR级别如何避免幻读

    幻读定义

    事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象 发生了幻觉一样。

    mysql如何实现避免幻读

    1.在快照读读情况下,mysql通过mvcc来避免幻读。

    2.在当前读读情况下,mysql通过next-key来避免幻。

    什么是MVCC

    mvcc全称是multi version concurrent control(多版本并发控制)。mysql把每个操作都定义成一个事务,每开启一个事务,系统的事务版本号自动递增。每行记录都有两个隐藏列:创建版本号和删除版本号

    select:事务每次只能读到创建版本号小于等于此次系统版本号的记录,同时行的删除版本号不存在或者大于当前事务的版本号。

    update:插入一条新记录,并把当前系统版本号作为行记录的版本号,同时保存当前系统版本号到原有的行作为删除版本号。

    delete:把当前系统版本号作为行记录的删除版本号

    insert:把当前系统版本号作为行记录的版本号

    什么是next-key锁

    行锁+GAP间隙锁

    什么是快照读和当前读

    快照读:简单的select操作,属于快照读,不加锁。(当然,也有例外,下面会分析)

    select * from table where ?;

    当前读:特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。

    select * from table where ? lock in share mode;

    select * from table where ? for update;

    insert into table values (…);

    update table set ? where ?;

    delete from table where ?;

    展开全文
  • 怎么防止oracle幻读,脏读

    千次阅读 2018-03-31 23:36:43
    怎么防止oracle幻读,脏读 711EK61 | 浏览 22 次 |举报 我有更好的答案 ...如果防止oracle出现幻读和不可重复读,只能把事务级别设置成SERIALIZABLE隔离级别才能避免幻读。语法:SET TRA

    怎么防止oracle幻读,脏读

    711EK61 | 浏览 22 次 |举报
    我有更好的答案
    2018-01-04 最佳答案
    oracle默认的事务级别是READ COMMITTED:允许幻读、不可重复读,不允许脏读的。
    如果防止oracle出现幻读和不可重复读,只能把事务级别设置成SERIALIZABLE隔离级别才能避免幻读。语法:SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
    展开全文
  • InnoDB可重复读隔离级别下如何避免幻读? 表象:快照读(非堵塞读) 在Repeatable-read隔离级别下,如果先在别的事务操作数据之前,创建了快照读,不管别的事务怎么操作数据,当前事务再次使用快照读时,查到的...
  • 一些文章写到InnoDB的可重复读避免了“幻读”(phantom read),这个说法并不准确。做个试验:(以下所有试验要注意存储引擎和隔离级别)试验一:如此就出现了幻读,...那么,InnoDB指出的可以避免幻读怎么回事呢?h...
  • Mysql加锁过程详解(2)-关于mysql 幻...那么,InnoDB指出的可以避免幻读怎么回事呢?By default, InnoDB operates in REPEATABLE READ transaction isolation level and with the innodb_locks_unsafe_for_binlog s...
  • 4种事务: 串行读:事务串行执行,效率最低 可重复读:一个事务不会去修改已经...避免不了幻读以及不可重复读,比如现在a读到b为1,在它操作前,c把b+1了,那么现在a读到的b为2,这就乱套了。 脏读:一个事务读...
  • Mysql加锁过程详解(2)-关于mysql 幻...那么,InnoDB指出的可以避免幻读怎么回事呢? http://dev.mysql.com/doc/refman/5.0/en/innodb-record-level-locks.html By default, InnoDB operates in REPEATABLE RE...
  • Mysql加锁过程详解(2)-关于mysql 幻读理解出现了幻读,那么不是说mysql的重复读解决了幻读的...那么,InnoDB指出的可以避免幻读怎么回事呢? http://dev.mysql.com/doc/refman/5.0/en/innodb-record-level-l...
  • 面经总结1

    2020-11-20 09:14:53
    数据库隔离级别,怎么避免幻读 B+树,为什么用B+树 哈希表的数据结构,怎么解决哈希冲突,为什么链表太长了要用红黑树,为什么不直接用红黑树 红黑树和二叉平衡树 进程和线程的区别,通信 linux查看进程,查看端口...
  • 面试准备0

    2020-04-29 22:24:53
    如果现在访问量特别大,该怎么避免幻读?(串行化) GC如何识别垃圾(根可达算法和引用计数) GC工作时对引用等级的了解(强软若虚四种引用)← 还做过什么项目用Nett做了一个基于网络的聊天的项目,实现了,,, 对...
  • 幻读:A事物中同查询语句不幂等,读到新插入数据。数据库事务隔离级别串行化(Serializable):一个事务执行过程中完全看不到其他事务,但如果其他事务在操作,只能停等;可避免以上五个问题。可重复读(Re...
  • 微信搜索“coder-home”或扫一扫下面的...文章目录事务并发问题的验证读未提交隔离级别脏读是如何发生的不可重复读是如何发生的幻读是如何发生的读已提交隔离级别脏读是如何避免的不可重复读是如何发生的幻读是如何.
  • 文章目录1. 什么是锁2. mysql Innodb 锁类型2.1 共享锁... 利用锁解决的问题4.1 利用锁怎么解决脏读4.2 利用锁怎么解决不可重复读4.3 利用锁怎么解决幻读5. 死锁5.1 死锁产生的条件5.2 避免死锁 1. 什么是锁 锁是用于管
  • mysql事务

    2019-04-21 11:10:24
    A:原子性 事务的操作都不可再分 C:一致性 从一个一致状态到另一个一致的状态 比如说转账场景...隔离级别:read-uncommited (最低) read_commited 可以避免脏读,不可避免不可重复读和幻读 repeatable 可重复读 seri...
  • 为什么InnoDB的next_key机制为什么能避免幻读 说说什么是幻读,那你能知道next_key的原理了吗? 说说你项目里的难点 为什么要用逻辑外键,而不用数据库的外键 怎么建索引,有什么技巧 说说悲观锁和乐观锁的区别 什么是...
  • 面经--百度知道

    2020-02-09 17:52:12
    项目设计到mysql联合查询,问到了数据库事务的隔离级别,每个隔离级别存在的问题,如何解决(读已提交造成幻读的场景,以及可重复读怎么解决的, 当时回答可重复读也会造成幻读,通过加共享锁和排他锁进行避免) ...
  • 幻读是什么?哪些可以避免换的? 5、两个系统的事务怎么进行通信的,例如工商银行和农业银行进行两个事务的通信? 分布式事务处理:1)全局消息;2)基于可靠消息事务服务;3)最大通知; 银行,基于可靠消息服务...
  • 小米面经6(广州)

    2018-10-20 02:45:25
    java基础,数据库,计算机网络,数据结构 数据库就问了隔离级别和索引,计网问了滑动窗口协议,tcp/ip四层结构,tcp和udp,tcp怎么保持可靠性...1、Serializable (串行化):可避免脏读、不可重复读、幻读的发生。 ...
  • 1、MySQL用的挺多,问你一下,innodb的b+树索引,主键索引,聚簇索引有什么区别。...MySQL的RR避免幻读,所以读不到新增数据。 4、MySQL的死锁怎么产生的,举了两个例子。 5、三个事务,两个加...
  • MVCC的基本概念 ...读-写:线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读。 写-写:线程安全问题,可能会存在更新丢失问题。 什么是MVCC MVCC,全称 Multi-Version Concur
  • 什么是脏读,幻读,不可重复读?如何避免?mysql的锁类型?什么是死锁?msyql是如何解决死锁的?mysql存储引擎的种类,以及他们的区别?使用场景?如何查看表状态,如表大小,行数,索引大小,行格式...什么是mysql基准...
  • 面试-1

    2019-06-03 18:19:07
    避免资源竞争,多实例运行时会对数据库或者redis各种资源竞争,避免竞争出现的脏读,盲读,幻读 等。 遇到服务端卡顿怎么定位 这个就是考验对线上服务的运维经验。 首先确保网络有没有问题,一般使用阿里云或者自建...
  • 作业帮一面+二面+hr面

    千次阅读 2020-08-21 14:46:03
    这是本菜鸡秋招面的第二家公司,写面经来记录自己的秋招成长史,等以后工作了回过...7.你的图片服务器项目中,怎么解决脏读幻读问题的 8.死锁的条件以及避免死锁的办法 9.写数据库语句,学生表啥的 10.linux指令 11.讲
  • java面经信息总结

    2021-03-26 15:56:39
    快手后端 1 1号面经来源-----2021 快手后端开发秋招面试总结 9.22 号 一面 (56min) 自我介绍 介绍一下Java中的集合类,主要讲了hashmap和correctHashMap ...mysql的隔离级别,mysql如何解决幻读 redi
  • 以及记好交房时的水、电、气的用量数 以上信息在退租时也会进行同样的检查。但要注意看清楚合同退房的要求,是提前多少天及怎样告知,即使房东跟你说不需要,到时说一声就行,你要真信了,到退房的时候他可能就拿...

空空如也

空空如也

1 2
收藏数 30
精华内容 12
关键字:

怎么避免幻读