MySQL(一)MySQL中的隔离级别,事务详解

MySQL的基础语法,增删改查就不多赘述了,我打算直接从事务开始,以后如果写到了,再补充相关的知识。

参考文章:

https://www.cnblogs.com/songjy2116/p/7881294.html

https://blog.csdn.net/alexdamiao/article/details/51872477

目录

一、什么是事务?

二、事务四大特征(ACID)

三、事务的原理

 1.undo日志文件

 2. redo 日志文件

 3.Undo + Redo事务的特点

 4.为了保证Redo Log能够有比较好的IO性能,InnoDB 的 Redo Log的设计有以下几个特点:

四、事务的隔离级别

五、不考虑隔离级别可能造成的后果

六、隔离性实现的原理


一、什么是事务?

  • 事务:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元)
  • MySQL 事务主要用于处理操作量大,复杂度高的数据。
  • 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
  • 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
  • 事务用来管理 insert,update,delete 语句。

示例:银行转账问题

   创建 人员-金额 表如下:

 

  现在丙要给乙转账500元,对应的sql如下:

UPDATE money set money = 500 where name = '丙'
UPDATE money set money = 1500 where name = '乙'

  这两句sql必须要同时执行成功,如果其中一条失败另外一条也不能成功执行,否则就会出现丙扣了钱但是乙没有收到钱这种情     况,这个时候就需要用到事务,将这两句sql放到同一个事务下。

 二、事务四大特征(ACID)

  • 原子性(A):事务是最小单位,不可再分
  • 一致性(C):事务要求所有的DML语句操作的时候,必须保证同时成功或者同时失败
  • 隔离性(I):事务A和事务B之间具有隔离性
  • 持久性(D):是事务的保证,事务终结的标志(内存的数据持久到硬盘文件中)

三、事务的原理

原子性、一致性和持久性是通过redo 和 undo 日志文件实现的,不管是redo还是undo文件都会有一个缓存我们称之为redo_buf和undo_buf。同样,数据库文件也会有缓存称之为data_buf。

   1.undo日志文件

undo记录了数据在事务开始之前的值,当事务执行失败或者ROLLBACK时可以通过undo记录的值来恢复数据。例如 AA和BB的初始值分别为3,5。
A 事务开始
B 记录AA=3到undo_buf
C 修改AA=1
D 记录BB=5到undo_buf
E 修改BB=7
F 将undo_buf写到undo(磁盘)
G 将data_buf写到datafile(磁盘)
H 事务提交
  • 通过undo可以保证原子性、一致性和持久性 
  • 如果事务在F之前崩溃由于数据还没写入磁盘,所以数据不会被破坏。 
  • 如果事务在G之前崩溃或者回滚则可以根据undo恢复到初始状态。 
  • 数据在任务提交之前写到磁盘保证了持久性。 
  • 这里有一个隐含的前提条件:‘数据都是先读到内存中,然后修改内存中的数据,最后将数据写回磁盘’。
  • 但是单纯使用undo保证原子性和持久性需要在事务提交之前将数据写到磁盘,浪费大量I/O。

 2. redo 日志文件

如果能够将数据缓存一段时间,就能减少IO提高性能。但是这样就会丧失事务的持久性。因此引入了另外一
种机制来实现持久化,即Redo Log.

A 事务开始
B 记录AA=3到undo_buf
C 修改AA=1 记录redo_buf
D 记录BB=5到undo_buf
E 修改BB=7 记录redo_buf
F 将redo_buf写到redo(磁盘)
G 事务提交
  • 通过undo保证事务的原子性,redo保证持久性。 
  • F之前崩溃由于所有数据都在内存,恢复后重新冲磁盘载入之前的数据,数据没有被破坏。 
  • FG之间的崩溃可以使用redo来恢复。 
  • G之前的回滚都可以使用undo来完成。

 3.Undo + Redo事务的特点

  • 为了保证持久性,必须在事务提交前将Redo Log持久化。
  • 数据不需要在事务提交前写入磁盘,而是缓存在内存中。
  • Redo Log保证事务的持久性。
  • Undo Log保证事务的原子性。
  • 有一个隐含的特点,数据必须要晚于redo log写入持久存储。

Undo + Redo的设计主要考虑的是提升IO性能。虽说通过缓存数据,减少了写数据的IO. 但是却引入了新的IO,即写Redo Log的IO。如果Redo Log的IO性能不好,就不能起到提高性能的目的。

 4.为了保证Redo Log能够有比较好的IO性能,InnoDB 的 Redo Log的设计有以下几个特点:

  • 尽量保持Redo Log存储在一段连续的空间上。因此在系统第一次启动时就会将日志文件的空间完全分配。以顺序追加的方式记录Redo Log,通过顺序IO来改善性能。
  • 批量写入日志。日志并不是直接写入文件,而是先写入redo log buffer.当需要将日志刷新到磁盘时 (如事务提交),将许多日志一起写入磁盘.
  • 并发的事务共享Redo Log的存储空间,它们的Redo Log按语句的执行顺序,依次交替的记录在一起,以减少日志占用的空间。例如,Redo Log中的记录内容可能是这样的:

        记录1: <trx1, insert …>

        记录2: <trx2, update …>

        记录3: <trx1, delete …>

        记录4: <trx3, update …>

        记录5: <trx2, insert …>

  • 因为第三个原因,当一个事务将Redo Log写入磁盘时,也会将其他未提交的事务的日志写入磁盘。
  •  Redo Log上只进行顺序追加的操作,当一个事务需要回滚时,它的Redo Log记录也不会从Redo Log中删除掉。

事务的隔离级别

事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
读已提交(read-committed)
可重复读(repeatable-read)
串行化(serializable)
mysql默认的事务隔离级别为repeatable-read 

五、不考虑隔离级别可能造成的后果

  • 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
  • 不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
  • 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

六、隔离性实现的原理

这部分内容涉及到锁,数据库引擎,mvcc等内容,在下篇博客中单独做一章总结。

猜你喜欢

转载自blog.csdn.net/qq_41907991/article/details/83990391