• MySQL事务


    什么是事务

    事务就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。

    为什么要有事务

    1.事务是数据库维护数据一致性的基本单位,在每个事务结束时,都能保证数据一致性。

    2.事务的提出主要是为了解决并发情况下保持数据一致性的问题。

    如何使用事务

    对于单挑SQL语句,会被MySQL自动包装成事务。

    对于多条SQL语句,需要如下操作:

    begin //或者 start transaction
    SQL1;
    (savepoint p1; 中途可以设置回滚点)
    SQL2;
    ...
    (rollback p1; 回滚到设置的回滚点,若未设置,则默认回滚到事务最开始的状态)
    commit;
    

    事务的属性

    原子性

    一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

    隔离性

    隔离性是什么?

    隔离性是MySQL的内部机制,让并发执行的各个事务,看到不同的数据修改(增删改),就叫做隔离性。

    隔离级别是什么?

    我们作为一个事务,可以看到不同可见性的数据,程度的不同,叫做隔离级别。

    隔离级别解决的问题

    脏读

    一个事务执行时,读到了另一个事务未提交的数据。这种现象叫做脏读。

    不可重复读

    同一个事务内,同样的读取,在不同的时间段,读取到了不同的值。这种现象叫做不可重复读。重点是修改和删除。

    幻读

    幻读是不可重复读的一种特殊情况,重点在于新增。同样的条件,第一次和第二次读出来的记录数不一样。

    这里的幻读仅指插入,不包含更新或删除后,查询到不一样的记录数。

    一般的数据库在可重复读情况的时候,无法屏蔽其他事务insert的数据(为什么?因为隔离性实现是对数据加锁完成的,而insert待插入的数据因为并不存在,那么一般加锁无法屏蔽这类问题),会造成虽然大部分内容是可重复读的,但是insert的数据在可重复读情况被读取出来,导致多次查找时,会多查找出来新的记录,就如同产生了幻觉。这种现象,叫做幻读。很明显,MySQL在RR级别的时候,是解决了幻读问题的。

    隔离级别分类

    读未提交(Read Uncommited)

    在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多并发问题,如脏读,幻读,不可重复读等。

    读提交(Read Commited)

    该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读和幻读的问题。

    可重复读(Repeatable Read)

    这是 MySQL 默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题(MySQL解决了该问题)。

    串行化(Serializable)

    这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决了脏读、不可重复读和幻读等问题。它在每个读的数据行上面加上共享锁,但是可能会导致超时和锁竞争(这种隔离级别太极端,实际生产基本不使用)。

    如何做到隔离级别?

    MySQL通过MVCC机制实现了隔离级别。

    为什么要存在隔离级别?

    不仅仅是为了考虑安全问题,是在安全和效率之间,找平衡点。至于为什么存在多种隔离级别,是因为隔离级别的选择是由上层决定的,MySQL只是提供多种方案供上层选择。

    安全体现在:数据具有隔离性,MySQL在RR级别下帮我们解决了脏读、不可重复读和幻读等问题,所以我们读到的数据是安全的。

    效率体现在:在保证隔离级别的情况下,采用多版本并发控制(MVCC),让删,改,增加使用当前读,让读取使用快照读。对于同时进行的多事务而言时,因为隔离性的存在,写当前数据,读历史数据,使得当前读和快照读并发执行。

    持久性

    事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

    一致性

    在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。

    一致性不是一种具体的方案,而是事务维护的最终目标。由用户和MySQL共同决定

    RC与RR的本质区别

    三个列隐藏字段

    • DB_TRX_ID :6 byte,最近修改( 修改/插入 )事务ID,记录创建这条记录/最后一次修改该记录的事务ID。

    • DB_ROLL_PTR : 7 byte,回滚指针,指向这条记录的上一个版本(简单理解成,指向历史版本就行,这些数据一般在 undo log 中)。

    • DB_ROW_ID : 6 byte,隐含的自增ID(隐藏主键),如果数据表没有主键, InnoDB 会自动以 DB_ROW_ID 产生一个聚簇索引。

    • 补充:实际还有一个删除flag隐藏字段, 既记录被更新或删除并不代表真的删除,而是删除flag变了。

    undo log

    MySQL 中的一段内存缓冲区,用来保存日志数据。

    Read View

    1. 决定一个事务的可见性的数据结构,记录一个事务能看到那些历史版本的数据。

    2. 一个事务启动,一旦形成Read View,Read View如果不变,该事务可以看到的历史版本也就是确定的。一旦我们发生了快照读,读视图得到了确认,后续的快照读就会依赖首次出现的快照读。即某个事务中首次出现快照读,决定该事务后续快照读结果的能力。

    ReadView是MySQL底层中的一个类,其结构的核心字段如下:

     

    读的策略源码如下:

    RR级别下

    当一个事务首次 select(不加锁的快照读)时,会形成快照及Read View。一旦形成Read View,就不会再更新。所以RR级别下,没有不可重复读和幻读的问题。

    RC级别下

    一个事务在每次读快照时,都会新生成一个快照和Read View。所以RC级别下,会存在不可重复读的问题。

  • 相关阅读:
    《Linux运维实战:创建LVM挂载到指定目录》
    从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(九)文件服务篇(1):minio 单机与集群搭建
    Hbase,Phoenix,hive,Redis 内存数据库,220905,,
    WPF Material Design UI框架
    Zookeeper集群 + Kafka集群
    Pandas Dataframe中迭代行的几种方法
    延迟摄影渲染工具LRTimelapse 6 为你制作出延时摄影的效果
    RSA加密:非对称密钥,公开密钥算法
    截图快捷键ctrl加什么
    十三、SpringBoot错误处理底层组件和异常处理流程分析
  • 原文地址:https://blog.csdn.net/weixin_60954394/article/details/126574087