新手做网站推荐,网站搭建网,启业网查询官网,黑色风格网站主页面一般对于我们的业务系统去访问数据库而言#xff0c;它往往是多个线程并发执行多个事务的#xff0c;对于数据库而言#xff0c;它会有多个事务同时执行#xff0c;可能这多个事务还会同时更新和查询同一条数据#xff0c;所以这里会有一些问题需要数据库来解决我们来看看…一般对于我们的业务系统去访问数据库而言它往往是多个线程并发执行多个事务的对于数据库而言它会有多个事务同时执行可能这多个事务还会同时更新和查询同一条数据所以这里会有一些问题需要数据库来解决我们来看看如果多个事务要是对缓存里的同一条数据同时进行更新或者查询此时会产生哪些问题呢这里实际上会涉及到脏写、脏读、不可重复读、幻读四种问题。脏写脏写意思是说有两个事务事务 A 和事务 B 同时在更新一条数据事务 A 先把它更新为 A 值事务 B 紧接着就把它更新为 B 值。如图可以看到此时事务 B 是后更新那行数据的值所以此时那行数据的值是 B。而且此时事务 A 更新之后会记录一条 undo log 日志。因为事务 A 是先更新的它在更新之前这行数据的值为 NULL。所以此时事务 A 的 undo log 日志大概就是更新之前这行数据的值为 NULL主键为 XX那么此时事务 B 更新完数据的值为 B此时事务 A 突然回滚了就会用它的 undo log 日志去回滚。此时事务 A 一回滚直接就会把那行数据的值更新回 NULL 值。如图然后就尴尬了事务 B 一看为什么我更新的 B 值没了就因为你事务 A 反悔了把数据值回滚成 NULL 了结果我更新的 B 值也不见 了。所以对于事务 B 看到的场景而言就是自己明明更新了结果值却没了这就是脏写。所谓脏写就是我刚才明明写了一个数据值结果过了一会却没了。而它的本质就是事务 B 去修改了事务 A 修改过的值但是此时事务 A 还没提交所以事务 A 随时会回滚导致事务 B 修改的值也没了这就是脏写的定义。脏读假设事务 A 更新了一行数据的值为 A 值此时事务 B 去查询了一下这行数据的值看到的值是 A 值如图接着事务 B 拿着刚才查询到的 A 值做各种业务处理。但是接着坑爹的事情发生了事务 A 突然回滚了事务导致它刚才功能的 A 值没了此时那行数据的值回滚为 NULL 值。然后事务 B 紧接着此时再次查询那行数据的值看到的居然是 NULL 值。如图这就是脏读。它的本质是事务 B 去查询了事务 A 修改过的数据但是此时事务 A 还没提交所以事务 A 随时会回滚导致事务 B 再次查询就读不到刚才事务 A 修改的数据了这就是脏读。其实总结一句话无论是脏写还是脏读都是因为一个事务去更新或者查询了另外一个还没提交的事务更新过的数据。因为另外一个事务还没提交所以它随时可能会回滚那么必然导致你更新的数据就没了或者你之前查询到的数据就没了这就是脏写和脏读两种场景。不可重复读假设我们有一个事务 A 开启了在这个事务 A 里会多次对一条数据进行查询。然后呢另外有两个事务一个是事务 B一个是事务 C他们两都是对一条数据进行更新的。然后我们假设一个前提就是比如说事务 B 更新之后如果还没提交那么事务 A 是读不到的必须要事务 B 提交之后它修改的值才能被事务 A 读取到其实这种情况下就是我们首先避免了脏读的发生因为脏读的意思就是事务 A 可以读到事务 B 修改过还没提交的数据此时事务 B 一旦回滚事务 A 再次读就读不到了那么此时就会发生脏读问题。我们现在假设的前提是事务 A 只能在事务 B 提交之后读取到它修改的数据所以此时必然是不会发生脏读的但是此时会有另外一个问题叫做不可重复读。假设缓存页里一条数据原来的值是 A 值此时事务 A 开启之后第一次查询这条数据读取到的就是 A 值。如图接着事务 B 更新了那行数据的值为 B 值同时事务 B 立马提交了然后事务 A 此时还没提交。大家注意此时事务 A 是没提交的它在事务执行期间第二次查询数据此时查到的是事务 B 修改过的值B 值因为事务 B 已经提交了所以事务 A 是可以读到的如图紧接着事务 C 再次更新数据为 C 值并且提交事务了此时事务 A 在还没提交的情况下第三次查询数据查到的值为 C 值如下那么上面的场景有什么问题呢其实要说没问题也可以是没问题的毕竟事务 B 和 事务 C 都提交之后事务 A 多次查询查到它们修改的值是 OK 的。但是你要说有问题也可以是有问题的就是事务 A 可能第一次查询到 A 值那么它可能希望的是在事务执行期间如果多次查询数据都是同样的一个 A 值它希望这个 A 值是它重复读取的时候一直可以读到的。它希望这行数据的值是可重复读的但是此时明显 A 值是不可重复读的。因为事务 B 和事务 C 一旦更新值并且提交了事务 A 会读到别的值所以此时这行数据的值是不可重复读的。此时对于你来说这个不可重复读的场景就是一种问题上面描述的其实就是不可重复读的问题其实这个问题你说是问题也不一定就是什么大问题。因为这取决于你自己想要数据库是什么样子的如果你希望看到的场景是不可重复读也就是事务 A 在执行期间多次查询一条数据每次都可以查到其它已经提交的事务修改过的值那么就是不可重复读如果你希望这样子那也没问题。如果你期望的是可重复读但是数据库表现的是不可重复读让你事务 A 执行期间多次查到的值都不一样都的问题是别的提交过的事务修改过的那么此时你就可以认为数据库有问题这个问题就是「不可重复读」幻读脏写、脏读和不可重复读都分别代表了不同的数据库问题。脏写就是两个事务没提交的状况下都修改同一条数据结果一个事务回滚了把另外一个事务修改的值也撤销了所谓脏写就是两个事务没提交状态下修改同一个值。脏读就是一个事务修改了一条数据的值结果还没提交呢另外一个事务就读到了你修改的值然后你回滚了人家事务再次读就读不到了即人家事务读到了你修改之后还没提交的值这就是脏读了。而不可重复读针对的是已经提交的事务修改的值被你事务给读到了你事务内多次查询多次读到的是别的已经提交的事务修改过的值这就导致不可重复读。接着我们说说幻读。简单来说你一个事务 A先发送一条 SQL 语句里面有一个条件要查询一批数据出来如 SELECT * FROM table WHERE id 10。然后呢它一开始查询出来了 10 条数据。接着这个时候别的事务 B往表里插了几条数据而且事务 B 还提交了此时多了几行数据。如图接着事务 A 此时第二次查询再次按照之前的一模一样的条件执行 SELECT * FROM table WHERE id 10 这条 SQL 语句由于其他事务插入了几条数据导致这次它查询出来了 12 条数据。如图于是事务 A 开始怀疑自己的眼镜了为什么一模一样的 SQL 语句第一次查询是 10 条数据第二次查询是 12 条数据难道刚才出现幻觉了这就是「幻读」这个名词的由来幻读就是你一个事务用一样的 SQL 多次查询结果每次查询都会发现查到一些之前没看到过的数据。注意幻读特指的是你查询到了之前查询没看到过的数据。此时说明你是幻读了其实脏写、脏读、不可重复读、幻读都是因为业务系统会多线程并发执行每个线程可能都会开启一个事务每个事务都会执行增删改查操作。然后数据库会并发执行多个事务多个事务可能会并发地对缓存页里的同一批数据进行增删改查操作于是这个并发增删改查同一批数据的问题可能就会导致我们说的脏写、脏读、不可重复读、幻读这些问题。所以这些问题的本质都是数据库的多事务并发问题那么为了解决多事务并发问题数据库才设计了事务隔离机制、MVCC 多版本隔离机制、锁机制用一整套机制来解决多事务并发问题。