数据库事务的实现原理

1. 前言

都知道数据库事务有ACID特性(原子性、一致性、隔离型、持久性),本文简单聊一下它们的实现原理。

2. 日志文件

2.1. redo log

redo log叫做重做日志,是用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log),前者是在内存中,后者在磁盘中。

当事务提交之后会把所有修改信息都会存到该日志中。假设有个表叫做tb1(id,username) 现在要插入数据(3,ceshi)

数据库事务的实现原理_第1张图片

start transaction; 
select balance from bank where name="zhangsan"; 
// 生成 重做日志 balance=600 
update bank set balance = balance - 400; 
// 生成 重做日志 amount=400 
update finance set amount = amount + 400; 
commit;

数据库事务的实现原理_第2张图片

redo log 有什么作用?

mysql 为了提升性能不会把每次的修改都实时同步到磁盘,而是会先存到Boffer Pool(缓冲池)里头,把这个当作缓存来用。然后使用后台线程去做缓冲池和磁盘之间的同步

那么问题来了,如果还没来的同步的时候宕机或断电了怎么办?还没来得及执行上面图中红色的操作。这样会导致丢部分已提交事务的修改信息!

所以引入了redo log来记录已成功提交事务的修改信息,并且会把redo log持久化到磁盘,系统重启之后在读取redo log恢复最新数据。

总结:redo log是用来恢复数据的 用于保障,已提交事务的持久化特性。

2.2. undo log

undo log 叫做回滚日志,用于记录数据被修改前的信息。他正好跟前面所说的重做日志所记录的相反,重做日志记录数据被修改后的信息。undo log主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。

还用上面那两张表

数据库事务的实现原理_第3张图片

每次写入数据或者修改数据之前都会把修改前的信息记录到 undo log。

undo log 有什么作用?

undo log 记录事务修改之前版本的数据信息,因此假如由于系统错误或者rollback操作而回滚的话可以根据undo log的信息来进行回滚到没被修改前的状态。

总结:undo log是用来回滚数据的用于保障 未提交事务的原子性。

2.3. archive log

archive log(归档日志)是Oracle数据库中的概念,它其实是redo log的衍生物。

redo log file是LGWR进程从Oracle实例中的redo log buffer写入的,是循环利用的。就是说一个redo log file写满后,才写下一个。归档日志是当数据库运行在归档模式下时,一个redo log file写满后,由ARCn进程将重做日志的内容备份到归档日志文件下,然后这个redo log file才能被下一次使用。

不管数据库是否是归档模式,重做日志是肯定要写的。而只有数据库在归档模式下,重做日志才会备份,形成归档日志。

redo log是循环利用的,但是归档日志不是,它不断接收从redo log中写入的日志备份。因此到一定时间后,会导致数据库存储不够,影响数据库使用。我们一般都会执行一个定时脚本,在规定时间周期后,删掉保留周期前的归档日志文件。

3. 锁和MVCC基础

3.1. 锁

具体关于锁的知识,可以翻看前面的文章《数据库事务和锁》。简单来分,锁分为下面共享锁排他锁

  • 共享锁(shared lock),又叫做"读锁"

读锁是可以共享的,或者说多个读请求可以共享一把锁读数据,不会造成阻塞。

  • 排他锁(exclusive lock),又叫做"写锁"

写锁会排斥其他所有获取锁的请求,一直阻塞,直到写入完成释放锁。

因此通过读写锁,只有读读可以并行,但是写读写写都不能做到并行
事务的隔离性就是根据读写锁来实现的,这个后面再说。

3.2. MVCC基础

MVCC (MultiVersion Concurrency Control) 叫做多版本并发控制。

InnoDB的 MVCC ,是通过在每行记录的后面保存两个隐藏的列来实现的。这两个列,
一个保存了行的创建时间,一个保存了行的过期时间,
当然存储的并不是实际的时间值,而是系统版本号。

以上片段摘自《高性能Mysql》这本书对MVCC的定义。他的主要实现思想是通过数据多版本来做到读写分离。从而实现不加锁读进而做到读写并行

MVCC在mysql中的实现依赖的是undo log与read view

  • undo log :undo log 中记录某行数据的多个版本的数据。
  • read view :用来判断当前版本数据的可见性。

4. 事务的实现原理

前面讲的重做日志,回滚日志以及锁技术就是实现事务的基础。

  • 原子性:使用 undo log ,从而达到回滚。
  • 持久性:使用 redo log,从而达到故障后恢复。
  • 隔离性:使用锁以及MVCC,运用的优化思想有读写分离,读读并行,读写并行。
  • 一致性:一致性是通过原子性,持久性,隔离性来实现的。通过回滚,以及恢复,和在并发环境下的隔离做到一致性。

原子性,持久性,隔离性折腾半天的目的也是为了保障数据的一致性。总之,ACID只是个概念,事务最终目的是要保障数据的可靠性,一致性。

你可能感兴趣的