MySQL的事务和数据恢复

作者: 沐风之境

MySQL的事务和数据恢复

并发事务带来的问题

  • 脏读:某一个事务修改了数据,但未提交的情况下,这时另一个事务读取了该行数据。那么读取的这个事务读的数据称为脏数据。这种情况称为脏读
  • 不可重复读:在一个事务内,多次读取同一个数据,这个事务没有结束时,另一个事务修改了该数据,导致上一个事务中,多次读取的数据不一致的问题,因此称为不可重复读
  • 幻读:与不可重复读相似。一个事务读取了几行数据,在当前事务未提交的时候,另外一个事务插入了几条新的数据。前一个事务在随后的查询中发现新多了几条数据

不可重复读与幻读的区别:不可重复读出现在数据更新的事务中,如UPDATE语句中。而幻读出现在数据增删的情况中,如INSERT,DELETE语句中

MySQL的事务隔离等级

  • (READ-UNCOMMITTED)读取未提交: 允许读取未提交的数据,最低的隔离等级,可能会导致脏读,幻读,不可重复读。

  • (READ-COMMITTED)读取已提交: 允许读取已提交的数据, 避免了脏读, 但会存在不可重复读和幻读。

  • (REPEATABLE-READ)可重复读: MySQL默认的事务隔离等级,保证同一个字段的多次读取结果一致, 除非被本事务修改。避免了脏读,不可重复读,但有在幻读的可能。

  • (SERIALIZEABLE)串行化:最高的隔离等级,所有事务逐个执行,事务之间不存在干扰。

    数据库事务隔离等级的通俗总结的很好

  • 读未提交:别人改数据的事务尚未提交,在的事务中也能读到。

  • 读已提交:别人改数据的事务已经提交,在的事务中才能读到。

  • 可重复读:别人改数据的事务已经提交,在的事务中也不去读。

  • 串行:的事务尚未提交,别人就别想改数据。
    这4种隔离级别,并行性能依次降低,安全性依次提高。

    Spring的事务隔离等级

    package org.springframework.transaction.annotation;

    public enum Isolation {

    DEFAULT(-1),
    READ_UNCOMMITTED(1),
    READ_COMMITTED(2),
    REPEATABLE_READ(4),
    SERIALIZABLE(8);
    
    private final int value;
    
    private Isolation(int value) {
        this.value = value;
    }
    
    public int value() {
        return this.value;
    }
    

    }

和MySQL的事务隔离等级相互对应。值多了一个默认枚举类型,DEFAULT表示遵循数据库的事务隔离等级

Spring的事务传递行为

什么是事务的传播行为?比如在方法A中开启了事务,在事务B中也开启了事务,在执行期间事务的维护情况,就是事务的传播行为。总共有下面七种

  • REQUIRED:指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中;若当前没有事务,则创建一个新事务。这种传播行为是最常见的选择,也是 Spring 默认的事务传播行为。

  • SUPPORTS:指定的方法支持当前事务,但若当前没有事务,也可以以非事务方式执行。

  • MANDATORY:指定的方法必须在当前事务内执行,若当前没有事务,则直接抛出异常。

  • REQUIRES_NEW:总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕。

  • NOT_SUPPORTED:指定的方法不能在事务环境中执行,若当前存在事务,就将当前事务挂起。

  • NEVER:指定的方法不能在事务环境下执行,若当前存在事务,就直接抛出异常。

  • NESTED:指定的方法必须在事务内执行。若当前存在事务,则在嵌套事务内执行;若当前没有事务,则创建一个新事务。

    MySQL中如何查看当前数据库系统的事务隔离等级

mysql> show variables like 'transaction_isolation';

+-----------------------+----------------+

| Variable_name | Value |

+-----------------------+----------------+

| transaction_isolation | READ-COMMITTED |

+-----------------------+----------------+

事务隔离的实现原理

在MySQL的中InnoDB引擎下,每一次的更新都会生成一条undo日志,用于回滚操作。那他是如何做到事务之间的数据可见性隔离的呢?这里就涉及到MySQL的多版本并发控制(MVCC)。在启动MySQL事务的时候,每个事务会创建一个当前数据的视图。在可重复读的隔离等级下,不会因为其他的事务被提交而导致当前事务下出现数据不可重复读的问题。

那这个数据视图是什么呢?这个视图被称为一致性读视图是读提交可重复读隔离级别的实现。他没有物理实现,是根据事务执行期间动态计算得到的。

事务的创建逻辑

  1. 向InnoDB事务系统申请唯一的事务ID,是一个严格递增的ID
  2. 记录当前事务系统中活跃但未提交事务ID列表到当前的事务ID数组中,并严格排序,最小的ID为低水位ID,最大的ID+1为高水位ID

事务数据可见性的判断逻辑:

  1. 数据版本的事务ID如果小于当前事务的最小水位ID,说明是本事务创建前就提交的,可见
  2. 数据版本的事务ID如果大于最大水位ID,说明是在本事务创建后再创建的事务,肯定不可见
  3. 数据的版本事务ID如果在最小水位和最大水位之间,有两种情况
  4. 存在事务数组中,说明是由没提交的事务生成的,不可见
  5. 不在事务数组中,说明这个版本是由已提交的事务生成的,可见

那如果当前事务ID已经落后于最新的数据版本,那应该如果找到当前的数据版本的数据呢?那就需要undo log了,通过undo log计算出当前数据行针对当前事务的的数据版本

InnoDB存储引擎的锁的算法

  • Record lock:单个行记录上的锁
  • 在查询存在唯一索引的时候用来锁定单条记录
  • Gap lock:间隙锁,锁定一个范围,不包括记录本身
  • 设计的目的是解决多个事务将记录插入到同一个范围内,导致幻读问题
  • 如:查询条件中存在范围条件语句,如:between、> 、<、 <= 、>=等
  • Next-key lock:record+gap 锁定一个范围,包含记录本身
  • 设计的目的是解决幻读问题

MySQL是如何保证机器异常重启后不丢失数据的?

涉及到MySQL的数据更新机制。binlog(归档日志)和redolog(重做日志)。MySQL默认的InnoDB引擎会将更新数据先存在内存中,同时将记录redolog,该条redolog的状态是perpare,然后将操作提交至执行器。执行器收到任务后,写入binlog,同时调用引擎接口写入或更新数据,成功后将之前的redolog改为commit状态。

如果在更新或写入数据的过程中,机器出现崩溃。那么在机器在重启后,MySQL会首先去验证redolog的完整性,如果redolog中没有prepare状态的记录,则记录是完整的,就日记提交。如果redolog中存在prepare记录,那么就去验证这条redolog对应的binlog记录,如果这条binlog是完整的,那么完整提交redolog,否则执行回滚逻辑

参考资料

《MySQL实战45讲》—极客时间

https://www.funtl.com/zh/spring-transaction/spring-%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86-api

原文创作:沐风之境

原文链接:https://www.cnblogs.com/mufeng3421/p/13182639.html

更多推荐

更多
  • Azure数据工程指南-二十四、数据治理的权限 创建 azure 预览帐户,探索 azure 预览,探索词汇表,浏览资产,以编程方式使用预览,摘要,管理凭证和访问,创建扫描, 许多组织需要建立数据治理流程、标准和方法,并且已经能够使用内部 SQL Server 工具(如 Master
    Apache CN

  • Azure数据工程指南-二十二、Synapse 分析工作区 创建 Synapse 分析工作区,使用 Spark 探索样本数据,用 SQL 查询数据,用 SQL 创建外部表,摘要, 微软 Azure 数据平台的众多新增功能已经围绕许多类似的产品及其在现代 Azure 数据平台中的用途产生了兴奋和困
    Apache CN

  • Azure数据工程指南-二十三、数据块中的机器学习 创建 MLflow 实验,安装 MLflow 库,创建笔记本,选择性测井,自动记录,摘要, 寻求利用机器学习(ML)和人工智能能力的组织和开发人员花费大量时间构建 ML 模型,并寻求一种方法来简化他们的机器学习开发生命周期,以跟踪实验,
    Apache CN

  • Azure数据工程指南-二十一、将 Apache Spark 的 GraphFrame API 用于图形分析 安装 JAR 库,加载新数据表,将数据加载到数据块笔记本中,用顶点和边构建一个图,查询图表,寻找有图案的图案,用 PageRank 发现重要性,探索入度和出度度量,摘要,进行广度优先搜索,查找连接的组件, 图形技术使用户能够以图形的形式
    Apache CN

  • Azure数据工程指南-20 二十、部署 SQL 数据库先决条件,创建 Visual Studio SQL 数据库项目,安装 Visual Studio GitHub 扩展,导入 AdventureWorks 数据库,连接到 GitHub Repo 源代码控制,将
    Apache CN

  • Azure数据工程指南-十九、部署数据工厂更改 先决条件,创建 DevOps 持续集成构建管道,创建 DevOps 持续部署发布渠道,验证部署的数据工厂资源,摘要,Azure PowerShell 任务停止触发器,ARM 模板部署任务,Azure PowerShell 任务启动触发器
    Apache CN

  • Azure数据工程指南-十八、用于 Cosmos DB 的 Azure Synapse 链接 创建一个 Azure Cosmos DB 帐户,启用 Azure Synapse 链接,创建一个 Cosmos DB 容器和数据库,将数据导入 Azure Cosmos DB,在 Azure Synapse Analytics 中创建
    Apache CN

  • Azure数据工程指南-十六、流分析异常检测 先决条件,创建流分析输入和输出,创建实时电源 BI 仪表板,监控实时电源 BI 流,摘要,创建 Azure 流分析作业,创建物联网中心,创建 Power BI 服务,下载设备模拟器,添加流输入,添加流输出,编写流分析查询,启动流分析作业
    Apache CN

  • Azure数据工程指南-十七、使用 Apache Spark 的实时物联网分析 先决条件,创建物联网中心,创建数据块集群,安装 Maven 库,创建笔记本并运行结构化流查询,摘要,配置笔记本连接,开始结构化流,启动物联网设备模拟器,显示实时流数据,创建 Spark SQL 表,将流写入增量表, 实时物联网分析、高级
    Apache CN

  • Azure数据工程指南-十五、DeltaLake 为什么是酸性 DeltaLake,先决条件,创建并插入 DeltaLake,更新 DeltaLake,从 DeltaLake 删除,浏览增量日志,摘要,插入,更新,删除, 在使用 Azure Data Lake Storage Gen2
    Apache CN

  • 近期文章

    更多
    文章目录

      推荐作者

      更多