大白话说事务隔离级别(白菜级)
2021-10-03 10:33:16 14 举报
细说mysql事务隔离级别
作者其他创作
大纲/内容
在《高性能mysql》的第一章介绍mysql的时候就提到了事务和事物的隔离级别。首先说到:acid事务特性的实现是一件极其复杂的事情,任何数据库一旦支持这个,那就意味着,当你作为server部署的时候一定是需要更强大的cpu/更大的内存/更多的磁盘空间,而mysql这种分层的设计可以让不同的存储引擎自己决定要不要支持acid。这个思想很流弊,就像我们些程序的时候的面向接口编程,一个接口有很多种实现,具体不同的业务场景使用不同的实现,扩展性极高!当然,有点扯远了。。。这里主要是在看到后面介绍说:sql标准中定义了四种隔离级别,这个其实在以前学习的时候也有了解,但是没怎么care,现在看了后有些级别有点模糊,上网搜资料也只是介绍了下场景,但是当使用某种级别的时候具体有哪些影响,说的又很模棱两可,所以这里自己试着理解记录一下!
开篇致辞
写
线程(事务)一begin
可以看到,事务二第一次读到了余额是500于是送了客户一包纸巾,然后这个过程中客户充了1000后,事务二再次读到了1500又送了一桶油!实际上这次活动应该只送纸巾或者油!而由于两次读到的值不一样多送了一件礼品!
余额 = 300commit
读已提交
请大家放慢脚步!其实读已提交已经解决了脏读的问题,基本可用!但是有追求的我们“无法接受”多次读的值不一样,那么如何解决这个问题呢?答案其实也比较简单,我们整一个都写锁在这条数据,其他事务你只能读不准写,那么我这个事务不就坐着读,躺着读都是同一个值了嘛~
单行数据,咱可以加都写锁,但是范围数据不好整啊!如何解决这种幻读的问题呢?一个很简单的思路:表锁!(但是严重影响性能)还有一个思路:通过多版本并发控制(mvcc)后面详细说这玩意儿!
级别二:read committed读已提交
级别三:read repeatable可重复读
r: 余额=200
r: 余额=100
r: 余额=500
r: value = 1
w: 余额+100=200
读未提交
mysql - dbvalue = 1
这个不打算说,因为原理太简单了,让事务串行执行,就是大家排好队,一个一个来!啥,还不清楚?你就理解成redis一样,单线程处理数据!但是你没发跟人家redis比,人家是纯内存操作,你呢?呵呵~
r: 2<=v<4
两次不一致
commit
初始化两条记录
余额 = 1500commit
恭喜你,成功掌握了升钱之道,离牢狱之灾不远了。。。事务一改了余额后回滚,但是事务二却依旧按照回滚前的值更新余额,这样无缘无故的多了100块钱,爽啊~~
对比上面,已经是重大升级!只能读到别人已经提交的内容!这里其实已经是一大进步(大多数数据库默认都是这个级别,但是mysql不是。。。去你妹的),那么这个就完美了?如果别人一个事务里面需要多次读余额就会发生前后不一致的情况,这个叫 -> 不可重复读
w: 余额+1000=1500
读
r: 余额=1500
级别四:serialized串行化
w: 余额+100=300
w: value = value+1
线程(事务)二begin
顾名思义,就是可以读到别人尚未提交(commit)的内容,会发生一件很尴尬的事:如果别人改了值之后又后悔了(回滚),那么你其实是不知道的,那就出现很严重的业务问题 -> 脏读
是不是有点牵强?你说我完全可以只读一次啊,为啥要读两次呢?大傻子???兄弟,这就狭隘了!如果你是一个微服务架构的应用,在搞一个分布式系统,两个服务在同一个事务中,都需要去读余额,想想两次是不是就有可能出问题了呢?但是很多场景,这个又影响不大,所以这个争议很大,具体影响要看业务。。。
这个是mysql默认的事务隔离级别!就是为了你们一个事务里面多次读的数据是一致的!!!不过大兄弟,你以为这样就万无一失了?幼稚!没错当你读某条数据的时候加了锁,但是如果你范围读取多条数据又会出现 -> 幻读
线程(事务)一
级别一:read uncommitted读未提交
线程(事务)二
rollback
if(1000<=v<2000)送一桶油
背景
if(500<=v<1000)送一包纸巾
mysql - dbvalue = ?
初始都是500
0 条评论
下一页