首页 > 科技 > Python 之 MySql“未解之谜”07-- 不懂事务,面试官全程黑脸

Python 之 MySql“未解之谜”07-- 不懂事务,面试官全程黑脸

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 回滚未提交的事务

“女二”的出场,让“男二”发现了背后默默支持的人,“女二”和“男二”官宣让整个故事画上圆满的句号。自此,MySql 事务的 ACID 到此杀青。

总结

在InnoDB中,MySql 事务具有ACID的机制,这也是为什么 MySql 在 5.5版本后默认存储引擎从MyISAM替换到InnoDB的一个重要原因。

>>>Python 之 MySql“未解之谜”06-- 表示时间的用什么类型?

本文来自投稿,不代表本人立场,如若转载,请注明出处:http://www.sosokankan.com/article/1795383.html

setTimeout(function () { fetch('http://www.sosokankan.com/stat/article.html?articleId=' + MIP.getData('articleId')) .then(function () { }) }, 3 * 1000)