目录
好像面试问到这个是很经常的事,但是一看那些专业词汇就发懵,花了点时间看懂了,过段日子回头一想,好像又搞不清楚幻读和脏读有什么区别来着?几种事务隔离级别干嘛的来着?.这就是菜鸟的悲伤吗.害,所以重新看了一些优秀的文章,重新理解了一下给自己举了一个小例子,好像又茅塞顿开了(天知道下次会不会忘)
一个小例子
我妈年近中年,开了小餐馆,自己给自己打工,想着挣点钱花花总比每天坐吃山空的好.
刚开业的时候有客人来我家吃饭,我妈妈还在这捣鼓着编辑菜单呢,客人一来看了一眼菜单就看到佛跳墙才15块钱,心里暗喜,结果马上下单,一看菜单已经是50块钱一份了.什么情况?.噢,原来是我妈在提交之前发现这个价格搞错了,怎么可能才15块钱,于是就改成了50才提交.客人在我妈还没提交的时候就看到15块钱了,这个就是脏读~脏读嘛,就是读到了脏数据,啥是脏数据?就是还没提交的数据,没有最终确定要保留在数据库里面的数据.也就是,多个事务并发,事务A读到了事务B还没有提交的数据.
如何解决脏读问题,就是读已提交.客人只能看到已经提交的数据,那么就能保证他看到的菜单价格是对的.好的,现在客人要根据菜单进行点菜,虽然从15变成50,但还是很便宜啊,于是点了一份佛跳墙,就开始继续点其他的菜,在这期间呢,我妈忽然发现佛跳墙的食材都没买到呀,于是赶紧把佛跳墙的价格改成9999让顾客不要下单.客人选好了其他的菜,在线结算的时候发现,50块钱的怎么又变成了9999了.我靠,这个菜单怕不是有毒?这个就是不可重复读的问题.同一个事务前后读取的数据不一致,
那怎么办呢,就是可重复读.当客人选中这个菜,点了他的时候,就不允许其他人对这个价格进行更改了,就能保证客人在点单的整个过程中前后数据是一致的.可是我妈确实没有这个食材呀,这菜上不了可怎么办?害,只好去赔礼道歉了,小本生意不容易,这软件是我闺女开发的也不太好使见谅见谅.下次再来咱一定打折.
话说这个客人他今天特别想吃番茄炒蛋,但翻啊翻翻啊翻菜单都没找到,只好作罢.正在等菜呢,就听见旁边的顾客在讨论,哎他们家的番茄炒蛋上次吃了很好吃,咱们点一个.他又回去看菜单, 看见现在怎么又有番茄炒蛋啦!!原来是番茄炒蛋是下午特供菜,刚刚才加到菜单上去.这个就是幻读.就是第二次(或者第n次)读数据的时候,莫名其妙出现了原来没有的数据.
怎么解决,就是序列化.把写菜单,点菜这些事务顺序执行:
菜单写完了可以点单了吗?
还不能哦,还没提交呢.
提交完了,我可以点菜了吧
抱歉抱歉,价格还写错了
现在总可以点菜了
噢,还有一个下午特供菜番茄炒蛋要加上了.现在您可以点菜了.
据我的理解,大概就是这么一回事.哪里有不对的还希望多多指点.
对了,据说mysql默认事务隔离级别可重复度,oracle默认读已提交哦~
-
四大特性
-
acid,原子性,一致性,隔离性,持久性
-
-
并发事务下产生的问题
-
脏读:读到了另一个事务未提交的数据
-
不可重复读:同一个事务两次查询得到的数据不一致,因为其他事务更新了数据.[对应的是update操作]
-
幻读:事务A操作的时候,别的事务新增了数据,导致事务A读的时候会发现新增的数据没有更新.[对应insert操作]
-
-
事务隔离级别
为了解决上述问题,产生不同的级别.级别越高,安全性越高,同时性能消耗越大
-
read_uncommited,读未提交.就是读取未提交的数据嘛,显然解决不了上面的问题,所以很少用
-
read_commited.读已提交.就是读已经提交的事务,可以解决脏读的问题,但后面两种解决不了
-
repeatable_read.可重复读.重复读就是在一个事务进行查询数据的时候,给这些数据创建快照,在这个事务提交之前所有的查询结果都和最开始的查询是一样的.
-
serializable.串行化.就是让所有的事务按顺序执行,一个事务完全关闭了才能开启别的事务.耗能高,一般不用.
-
更新
经过实际验证发现,可重复读不是先前写的加锁而是创建快照,为此我还去找了好多博客和文章,好像写的都是可重复读是加锁,实际上不是如此,所以前文的可重复读的描述改了一下
说一下我的验证过程,在mysql中找到一个数据库,查询事务隔离级别,确定是REPEATABLE-READ
1.开启事务A,查询数据的结果为
2.开启事务B,更新数据并提交,此时在事务B和其他事务查询的结果是,说明已经更新成果
3.在事务A中再次查询,反复查询,结果都是
4.提交事务A,再次查询,结果就变成了
因此,可重复读应该是在事务开始的时候,创建查询数据内容的快照的,以这种方式保持事务A的查询结果一致,而不是给这些内容加锁.
我顺便验证了一些,在开启事务A的同时,事务B进行更新并提交,再在事务A中进行更新并提交会有什么效果..然后发现我好傻,当然是根据事务提交的先后顺序对数据进行变更了!A最后提交,就按照A更新的结果呗