数据库事务(mysql数据库为例)

2021-07-22  本文已影响0人  云芈山人
Mysql事务.png

概念

数据库事务( transaction)是访问并可能操作各种[数据项]的一个数据库操作[序列],这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。

性质(ACID)

  1. 原子性(Atomicity)
    事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。
  2. 一致性(Consistency)
    几个并行执行的事务,其执行结果必须与按某一顺序 串行执行的结果相一致。
  3. 隔离性(Isolation)
    事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
  4. 持久性(Durability)
    对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。

事务的ACID特性是由关系数据库系统来实现的,DBMS采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所作的更新,如果某个事务在执行过程中发生错误,就可以根据日志撤销事务对数据库已做的更新,使得数据库回滚到执行事务前的初始状态。

对于事务的隔离性,DBMS是采用锁机制来实现的。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。

事务想要做到什么效果?

一、redo log 与 undo log

1. redo log

当事务提交之后会把所有修改信息存到该日志中。如下:


数据原始状态.png
start transaction;
select balance from bank where name="ls";
// 生成 重做日志 balance=800
update bank set balance = balance - 200; 
// 生成 重做日志 amount=200
update finance set amount = amount + 200;
commit;
redo log过程.png

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

2. undo log

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

二、mysql锁技术以及MVCC基础

1. mysql锁技术

通过读写锁,可以做到读读可以并行,但是不能做到写读,写写并行,事务的隔离性就是根据读写锁来实现的。

2. MVCC基础

InnoDB的 MVCC ,是通过在每行记录的后面保存两个隐藏的列来实现的。这两个列, 一个保存了行的创建时间,一个保存了行的过期时间,当然存储的并不是实际的时间值,而是系统版本号。
他的主要实现思想是通过数据多版本来做到读写分离。从而实现不加锁读进而做到读写并行。

三、事务的实现

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

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

1. 原子性的实现

什么是原子性:
一个事务必须被视为不可分割的最小工作单位,一个事务中的所有操作要么全部成功提交,要么全部失败回滚,对于一个事务来说不可能只执行其中的部分操作,这就是事务的原子性。--《高性能MySQL》

数据库是怎么实现的呢?就是通过回滚操作。

回滚操作就是当发生错误异常或者显式的执行rollback语句时需要把数据还原到原先的模样,所以这时候就需要用到undo log来进行回滚。

1.1 undo log 的生成

undo log过程.png
undo log 的生成.png

1.2 根据undo log 进行回滚

2. 持久性的实现

事务一旦提交,其所作做的修改会永久保存到数据库中,此时即使系统崩溃修改的数据也不会丢失。

MySQL的数据存储机制:
MySQL的表数据是存放在磁盘上的,因此想要存取的时候都要经历磁盘IO,然而即使是使用SSD磁盘IO也是非常消耗性能的。

为了提升性能InnoDB提供了缓冲池(Buffer Pool),Buffer Pool中包含了磁盘数据页的映射,可以当做缓存来使用。

上面这种缓冲池的措施虽然在性能方面带来了质的飞跃,但是它也带来了新的问题,当MySQL系统宕机,断电的时候可能会丢数据(因为我们的数据已经提交了,但此时是在缓冲池里头,还没来得及在磁盘持久化,所以我们急需一种机制需要存一下已提交事务的数据,为恢复数据使用)。于是就有 redo log了。

事务开始之后就产生redo log,redo log的落盘并不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入redo log文件中。

redo log也需要存储,也涉及磁盘IO,为什么还使用它?

3. 隔离性的实现

隔离性是事务ACID特性里最复杂的一个。在SQL标准里定义了四种隔离级别,每一种级别都规定一个事务中的修改,哪些是事务之间可见的,哪些是不可见的。

级别越低的隔离级别可以执行越高的并发,但同时实现复杂度以及开销也越大

Mysql 隔离级别有以下四种(级别由低到高):

理解了隔离级别以及他的实现原理就相当于理解了ACID里的隔离型。原子性,隔离性,持久性的目的都是为了要做到一致性,但隔离型跟其他两个有所区别,原子性和持久性是为了要实现数据的可性保障靠,比如要做到宕机后的恢复,以及错误后的回滚。隔离性是要管理多个并发读写请求的访问顺序。这种顺序包括串行或者是并行(请求不仅仅是指insert操作,又包括update操作)。

隔离性.png

从隔离性的实现可以看出这是一场数据的可靠性与性能之间的权衡。

3.1 READ UNCOMMITTED(未提交读)

3.2 READ COMMITTED (提交读)

在每次select之间有其他事务更新了我们读取的数据并提交了,那就出现了不可重复读。


提交读级别下的读写锁的使用.png

3.3 REPEATABLE READ (可重复读)(Mysql默认隔离级别)

但是在该隔离级别下仍会存在幻读的问题。

3.4 SERIALIZABLE(可串行化)

3.5 总结

SQL隔离级别.png

4. 一致性的实现

在涉及并发的情况下往往在性能和一致性之间做平衡,做一定的取舍,所以隔离性也是对一致性的一种破坏

幻读

幻读.png
上一篇下一篇

猜你喜欢

热点阅读