I
One Day
Python小新 心事重重
唉声叹气地在走廊徘徊
经过 Python大星 的一番询问
原来最近 Python小新 参加了一场面试
面试官全程黑脸,吐槽他底子太差,事务不知道ACID,
说这个24岁的年轻人不懂如何学习和沉淀,过早地丧失竞争力真是太可怕了,
奉劝年轻的程序员千万别偷懒,导致提前消费了自己的竞争力
小试牛刀
下列不是MySql事务的ACID特性? 单选
0人
0%
A.原子性
0人
0%
B.一致性
0人
0%
C.共享性
0人
0%
D.隔离性
0人
0%
E.持久性
先看一个 Python 小程序:模拟银行转账功能
● Python 代码:>>>
● Python 代码输出结果:>>>
这个小程序,看似没什么问题
但是,在实际使用过程中,存在重大的漏洞 bug
● 比如 隔壁老王 欠 Python大星 money,隔壁老王 余额已经扣除,但是由于银行系统故障, Python大星的账户却没有增加相应的 money,玩呢?!如果银行这么 low,早倒闭了
一般到这个时候,“男一”(花名:原子性)就该闪亮登场
名称由来:原子是不可分割的整体。
事务把数据库的多个操作打包成一个整体,要么都成功,要么都失败,不存在中间状态。
就像银行系统场景 隔壁老王 转账给 Python大星 时:
● 不允许 隔壁老王 的余额扣钱了,Python大星 的余额却没增加
● 不允许 Python大星 的余额增加,隔壁老王 的余额却没有扣除
MySql 如何实现原子性的呢?
作为“男一”的原子性怎能没有“神器”在手呢?
月光宝盒
“月光宝盒”:undo log(回滚日志) ,当剧情和我们想的不一样时,时光会倒流,一切如初
注意:是先写日志后写硬盘
undo log
如果 undo log日志某一环节出现问题,MySql 会回滚原有数据。
上面只说了一个事务的情况,如果出现2个事务呢?
在隔壁老王给Python大星转账的事务期间,Python小新给Python大星转账200元的事务成功,
但是隔壁老王这个事务失败,会触发回滚,如果把Python大星的余额回滚到0,多么糟糕!!!
别怕,我们“女一号”(花名:一致性)她来了
如果我们一个事务对数据操作完了以后,另一个事务再进入,这样就不会发生争抢和数据不一致了。“女一”的能力是“魅惑”(加锁),对事务的开始和提交分别加锁和解锁。
从此,“男一”和“女一”守护世界和平,过上了童话般的生活
一切看似风平浪静,但是暗地里却波涛汹涌
如果要保证强一致性,最好的方法就是不管读写,统统排队进行,这样一定不会出现数据不一致的情况,
“男一”和“女一”(还未“结婚生子”)并发度太低
其他人就还有机会
说时迟,那时快
“男二”(花名:隔离性)的出现打破了长久的平静
“男二”采取了四步“隔离法”
事务的隔离机制
● 读未提交
事务A:“男一”给“女一”送了 11 朵玫瑰花,代表“爱你一心一意”
事务B:“男二”通过秘书在“男一”送花到“女一”手上(事务A结束)之前得知花的数量为11
● 读已提交
事务A:“男一”给“女一”送了 11 朵玫瑰花,代表“爱你一心一意”
事务B:“男二”通过秘书在“男一”送花到“女一”手上(事务A结束)之后得知花的数量为11
● 可重复读
事务A:“男一”给“女一”送了 11 朵玫瑰花,代表“爱你一心一意”
事务B:“男二”给“女一”送了 1314 朵玫瑰花,代表“爱你一生一世”,后来得知“男一”送了11朵玫瑰花
“读已提交” 和 “可重复读” 到底有什么异同?
相同点:
解决了“脏读”问题,所谓“脏读”,就是在“男一”事务 A没提交前, “男二”是不知道“女一”手上的玫瑰花有多少?
不同点:
“读已提交”中“男一”在给“女一”送花的途中,一开始得知“女一”手上没有玫瑰花,但是期间“男二”送了“女一” 1314 朵玫瑰花后,“男一”默默收起了玫瑰花。
“可重复读”中“男一”在给“女一”送花的过程中,不管“男二”有没有给“女一”送花,“男一”始终认为“女一”手中没有花。
可重复读的隔离级别下使用了 MVCC 机制,select 操作不会更新版本号,是快照读(历史版本);insert、update 和 delete 会更新版本号,是当前读(当前版本)。
● 串行化
事务A:“男一”给“女一”发信息,我要给你一个礼物,等我
事务B:“男二”也想送礼物给“女一”,“女一”对“男二”:对不起,我已经有“男朋友”啦
七夕,你给女朋友送什么礼物? 单选
0人
0%
A.包
0人
0%
B.化妆品套装
0人
0%
C.手表
0人
0%
D.花
0人
0%
E.其他
0人
0%
F.请先给我派送一个女朋友
为了让剧情有个圆满的结局
默默无闻的“女二”(花名:持久性)作为“男二”的秘书
是全程的观察者,她有一本“吸血鬼日记”(redo日志)记录了“男一”、“男二”和“女一”的故事
● 在七夕约会送花(事务)没有异常的情况下
注意:redo 日志必须先于数据写入磁盘(序号 7 和序号 8 不可颠倒顺序)。如果顺序颠倒,在数据写入磁盘时,一旦 redo 日志的写入过程出现 bug,将无法保证持久性。另外,在记录 redo 日志时,先记入 redo log buffer ,最后在一起写入磁盘,减少 IO,调高性能。
● 在七夕约会送花(事务)有异常的情况下
mysql的恢复策略:
● 恢复时,先根据 redo 重做所有事务(包括未提交和回滚)
● 再根据 undo 回滚未提交的事务
总结
在InnoDB中,MySql 事务具有ACID的机制,这也是为什么 MySql 在 5.5版本后默认存储引擎从MyISAM替换到InnoDB的一个重要原因。
>>>Python 之 MySql“未解之谜”06-- 表示时间的用什么类型?
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至123456@qq.com 举报,一经查实,本站将立刻删除。