前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mysql事务相关

Mysql事务相关

作者头像
心平气和
发布2021-10-26 10:06:21
3510
发布2021-10-26 10:06:21
举报
文章被收录于专栏:程序员升级之路

最近重温了下Mysql相关原理的书,主要是事务的实现,这个对设计一个稳定的系统很有借鉴意义,发现事务的实现还是蛮复杂的,把中间看到的一些知识点和想法整理下。

一、事务的核心属性

A:原子性

事务要么不执行,要么全部执行完,不会执行其中一部分;

B:一致性

主要是一些约束,如主键,外键,等

I:隔离性

指多线程之间的修改不会影响其它线程,如线程A改了数据没提交前B线程可以不看到,这个和事务隔离级别配置相关;

D:持久性

事务一旦提交了就不能丢失;

其中B主要是一些规则比较好理解,D也比较容易,事务提交的时候将数据全部刷新到存储介质上就行;A和I设计到多线程并发问题,还有异常处理问题,和D有些相关,如何保证提交的时候全部提交成功,而不会提交一部分。

二、Write-Ahead

数据库是IO型应用,对记录的修改最终是要写到磁盘上,一次事务可能修改多条记录,而这些记录会分布在磁盘的不同位置上,而磁盘是顺序写入性能高,下面是磁盘物理结构,具体组成就不介绍了;

如果大量随机磁道写入则会造成性能低下,所以有了Write-Ahead。

具体过程如下,数据库把对所有磁盘的修改以日志追加的方式写入,然后异步将这些内容刷新到真正存放数据的位置,这样就保证用户请求的时候性能是最高的;

举个例子,一个经典的例子是转账,需要将一个账上加钱,而另一个账上减钱,这个事务至少要执行2条Sql语句:

代码语言:javascript
复制
update User set balance=balance-100 where id=100;
update User set balance=balance+100 where id=200;

假设第一条记录在0号盘面上,第二条记录在1号盘面上,这个时候数据库记录2条日志,大概内容如下:

第1条日志:修改0号盘面X1磁道数据为Y1;

第2条日志,修改1号盘面X2磁道数据库Y2;

只要日志写入成功然后就可以返回给用户成功了,会有后台线程读取日志里的数据真正把0号盘面和1号盘面上的数据写回去。

可以看到,事务提交分成2部分,写日志和写数据,写日志记录数据改了哪些地方,这个和硬件相关,这部分是顺序写的;而写数据的部分是离散的,但这部分是后台写,所以性能慢一点没关系,要保证数据的正确性。

三、Redo Log

上面说了事务提交前后要写2部分数据,一是日志,二是数据,其中日志在Mysql准确的说是InnoDB中就是以Redo Log来表示,这里讲几个细节:

1、Redo Log以Redo Log Block来管理日志,每个Block是512字节,为什么是512,因为早期磁盘一个扇区就是512,这样可以保证写入的原子性,即不会512字节只会写一部分成功

2、日志文件不能无限扩张

日志过了一段时间就不需要了,这个时间是指数据的部分写入完成,因为这部分是异步写入的,如果中间当机则需要通过日志部分来恢复。

3、LSN(Log Sequence Number)

Redo Log日志编号,记录的是数据库从安装启动开始到当前写入的总的日志总量。这个用于恢复中,先不讲太细的东西。

四、ARIES恢复算法

这个是20世纪90年代IBM几位研究员提出的一个算法集,主要论文如下:

AREIS: A Transaction Recovery Method Supporting Fine-Granularity Locking and Parial Rollbacks Using WriteAhead Logging

这个算法影响深远,基本上现在的关系型数据库都吸收了这个思想。

先大概讲下基本原理,Mysql InnoDB中是以页为最小单位来管理磁盘的,一般为16KB,如果一个事务修改了某个页会将这个页标记为脏页,然后异步刷新到磁盘上。

ARIES算法大概分3个阶段:

1、分析阶段

确定哪些数据页是脏页,为阶段2的Redo做准备。

2、确定哪些事务未提交

未提交的事务也写入Redo Log,如何判断哪些未提交呢,这里用到了Checkpoint机制,它是每隔一段时间将内存中的所有数据刷新到磁盘,注意是所有,对于数据库的场景来说,现在几百GB大小很常见了,这样做肯定不现实,一个是量太大,二是刷新过程中还要停止所有用户请求,像JAVA垃圾回收一样,要Stop The World。

所以一般采用Fuzzy CheckPoint,具体是在内在中维护二张表:活跃事务表和脏页表。

活跃事务表:维护一个关键变量LastLSN,即该事务产生的日志最后一条日志的LSN。

脏页表是当前所有未刷新到磁盘上的页的集合,系统为每个页记录了RecoveryLSN,即导致该页面为脏页最早的LSN。

Fuzzy CheckPoint就是对这2个关键表做一个Checkpoint,这样数据量就比较小了,形成一条日志写入Redo Log。

有了这2张表就可以取出系统意外宕机的时候未提交的事务了,具体过程如下,从最近一次CheckPoint开始扫描Redo Log,遇到一个事务则加入到集合,如果遇到事务提交的日志则将事务从集合中删除掉。

另外就是求宕机的时候未刷盘的脏页集合,从最后一个CheckPoint开始一直扫描,一直到Redo Log的结束,如果日志中记录的是新的页面就加入到脏页集合,当然这过程可能在误判,不过没关系,真正把Redo Log写入到数据存放真正位置是幂等的。在刷磁盘的时候,磁盘上每个页面会记录最后一次刷新的LSN,刷新过程中会判断两者的大小,如果页面的LSN比Redo Log的大则跳过这条日志。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员升级之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档