首页 > 数据库 >MySQL 事务机制

MySQL 事务机制

时间:2023-07-25 18:46:41浏览次数:40  
标签:事务 读取 幻读 重复 提交 MySQL 机制 数据

事务机制:

事务语法:

-- 开始事务
begin;
-- 或
start transaction;

-- 提交
commit;

-- 回滚
rollback;

-- 保存点
savepoint;

事务特性:

默认事务:

MySQL的事务 默认自动提交:在自动提交的状态下 每一条SQL就是一个事务 会被直接执行

手动开启事务后:则所有的SQL语句都在一个事务中 直到执行了commit或rollback

事务原则:
  1. 原子性(Atomicity)

    定义:

    • 原子性是指事务包括的所有操作要么成功 要么全部失败回滚

    实现:

    • InnoDB实现回滚 靠的是undo log(回滚日志)
    • 实现原子性的关键 是当事务回滚时能够撤销所有已经成功执行的sql语句
  2. 一致性(Consistency)

    定义:

    • 事务执行结束后 数据库的完整性约束没有被破坏 事务执行的前后都是合法的数据状态
      如果回滚数据 回滚的数据需要跟原来保持一致

      数据库的完整性约束包括但不限于:
      实体完整性(如行的主键存在且唯一)、列完整性(如字段的类型、大小、长度要符合要求)、外键约束、用户自定义完整性(如转账前后,两个账户余额的和应该不变)

    实现:

    • 保证原子性、持久性和隔离性 如果这些特性无法保证 事务的一致性也无法保证
    • 数据库本身提供保障,例如不允许向整形列插入字符串值、字符串长度不能超过列的限制等
    • 应用层面进行保障,例如如果转账操作只扣除转账者的余额,而没有增加接收者的余额,无论数据库实现的多么完美,也无法保证状态的一致
    • 一致性原则的维护相对于其他三个 更偏向数据的规范
  3. 隔离性(Isolation)

    定义:

    • 多个并发事务之间要相互隔离 对应的是MySQL的可串行化级别 但是在实际中 因为性能的原因很少使用可串行化级别

    实现:

    • (一个事务)写操作对(另一个事务)写操作的影响:锁机制保证隔离性
    • (一个事务)写操作对(另一个事务)读操作的影响:MVCC保证隔离性
  4. 持久性(Durability)

    定义:

    • 事务一旦被提交了 对数据库中的数据是永久性的 此时即使系统崩溃修改的数据也不会丢失

    实现:

    • 问题:InnoDB提供了缓冲池 虽然在性能方面带来了质的飞跃 但是当MySQL系统宕机、断电的时候可能会丢数据
      如果这个时候事务提交了 数据还未持久化到磁盘 那么数据也就会丢失
      因为我们的数据已经提交了 但此时是在缓冲池里头 还没来得及在磁盘持久化
      所以我们急需一种机制需要存一下已提交事务的数据 为恢复数据使用
    • 解决:redo log 重做日志
      虽然redo log和刷脏都是IO操作 但刷脏是随机IO 而redo log是追加操作属于顺序IO
      另外刷脏是以数据页为单位 一点小改动都需要整页写入 而redo log只包含真正需要写入的部分
事务状态:
  • Active:事务的初始状态,表示事务正在执行;
  • Partially Commited:在最后一条语句执行之后;
  • Failed:发现事务无法正常执行之后;
  • Aborted:事务被回滚并且数据库恢复到了事务进行之前的状态之后;
  • Commited:成功执行整个事务;
image-20210721225034057

隔离级别:

  1. 读未提交:
    • 概念:事务A可以读取到事务B修改过但未提交的数据 (没提交也能获取到数据
    • 问题:可能发生脏读、不可重复读和幻读问题 一般很少使用此隔离级别
  2. 读已提交
    • 概念:事务A只能在事务B提交后才能读取到事务B修改的数据 (提交后才能获取到
    • 问题:解决了脏读的问题 但可能发生不可重复读和幻读问题 一般很少使用此隔离级别
    • 加锁:数据的读取都是不加锁的 但是数据的写入、修改和删除是需要加锁的
  3. 可重复读 --MySQL的默认隔离级别
    • 概念:事务A在提交后 事务B也不能读取到事务A提交的修改 (开启后就不能获取到
    • 问题:解决了脏读和不可重复读的问题 可能发生幻读问题 实际开发级别
    • 加锁:数据的读写都是加锁的 不过是行锁 所以可以阻塞其他事务对于本事务内读数据的修改和删除 实现可重复读
      但是行锁只能控制修改和删除 而不能作用于新增 所以还是会出现幻读的现象 (应该是行锁 也可能是乐观锁 待确认)
  4. 可串行化
    • 概念:事务A提交前 事务B读写操作都会被阻塞 (事务只会一个一个的执行 只有都是读操作不会被阻塞)
    • 问题:各种问题(脏读、不可重复读、幻读)都不会发生 通过加锁实现(读锁和写锁) 出于性能考虑很少使用

事务并发:

并发问题:

  • 脏读:
    事务A读到了事务B未提交的数据 (如果最终事务B没有提交 那么这个数据就是不存在的)
    读取到不存在的数据 就是脏读

  • 不可重复读:
    在事务A执行过程中 事务B修改了事务A中读取的数据 导致事务A在前后读取的数据不一致
    (如果是两个同样条件的修改语句 出现不可重复读现象 会导致两条数据修改的结果不一致)
    重复读取数据不一致 就是不可重复读

  • 幻读:

    在事务A执行过程中 事务B添加了数据 添加的数据在事务A的读取范围内 导致事务A在前后读取到的数据不一致
    (同 不可重复读现象一样 会导致修改的数据结果不一致)
    读取到新增的数据 就是幻读

注意点:幻读和不可重复读的区别?

  • 幻读和不可重复读看起来很像 都是在事务执行中 被别的事务修改了读取的数据 导致前后数据不一致
    两者的区别在于
    • 不可重复读侧重于数据的修改
    • 幻读则是侧重于数据的新增
  • 原因:
    • 不可重复读没有对读操作的数据加锁 所以别的事务也可以修改 本事务读取的数据 最终造成不可重复读现象
    • 幻读对读数据加了锁 不过幻读的锁是行锁 所以只是不能修改删除而已 还是能添加 所以会出现幻读现象
      (应该是行锁 也可能是乐观锁 待确认)

并发控制:

锁机制:

参看 ↓ 数据库锁

MVCC:
  • MVCC可以使用 乐观(optimistic)锁悲观(pessimistic)锁来实现
  • 各数据库中都有对MVCC的实现 且实现方式都不相同
  • 应对高并发事务 MVCC比单纯的加锁更高效
  • InnoDB支持MVCC InnoDB存储引擎在数据库每行数据的后面添加了三个字段
  • MVCC只在 读已提交 READ COMMITTED可重复读 REPEATABLE READ 两个隔离级别下工作

隐藏字段:

标签:事务,读取,幻读,重复,提交,MySQL,机制,数据
From: https://www.cnblogs.com/AnotherVincent/p/17580622.html

相关文章

  • MySQL 锁机制
    数据库锁:概念:锁是计算机协调多个进程或线程并发访问某一资源的机制(避免资源争抢)分类:按粒度表级锁:锁定整个表开销小加锁快不会出现死锁锁定粒度大发生锁冲突的概率最高并发度最低数据库引擎总是一次性同时获取所有需要的锁以及总是按相同的顺序获取表锁从而避免死......
  • MySQL 日志机制
    日志机制:错误日志:当数据库无法正常启动时第一个定位错误日志数据库速度慢时也可以定位错误日志得到建议(如增大缓存池增大redologbuffer等)查询日志:没啥用就是记录查询而已应该是为了对应binlog记录修改的日志慢查询日志:捕获查询慢的情况配置:可以设置每分钟最多有......
  • MySQL 数据库连接
    数据连接:连接:MySQL驱动:mysql-connector-Java-XXX.jar数据库连接的建立及关闭是及耗费系统资源的操作,在多层结构的应用环境中,这种资源的耗费对系统性能影响尤为明显。通过DriverManager获得数据库连接的方式,一个数据库连接对象对应一个物理数据库连接,每次操作都打开一个物......
  • MySQL 容灾备份
    容灾备份:数据备份:直接对数据库进行备份:#数据库备份语句#不指定表名的话默认就是整个数据库备份#备份文件可以指定绝对路径mysqldump-u[用户名]-p[库名][表名]...>[备份文件.sql]#多个数据库备份语句mysqldump-u[用户名]-p--databases[库名][库名]......
  • MySQL 索引
    索引分析:索引概述:定义:MySQL官方对索引的定义:索引(Index)是帮助MySQL高效获取数据的数据结构。结论:索引是数据结构结构:MySQL支持多种存储引擎而各种存储引擎对索引的支持也各不相同因此MySQL数据库支持多种索引类型如BTree索引、哈希索引、全文索引等等目前大部分数据库......
  • kettle连接数据库报错:Error connecting to database: (using class org.gjt.mm.mysql.
    kettle连接MySQL报错但已经把相应的包放到kettle的lib目录下时,仍然报连接不上的错误,那可能是MySQL时区的问题。解决如下:登入MySQL修改为东八区的命令:方法一:mysql>setglobalmax_allowed_packet=1024*1024;mysql>setglobaltime_zone='+8:00';方法二:修改my.ini文件,在[mysql......
  • Mysql开启慢查询日志
    查看mysql的慢查询日志是否开启showvariableslike'%query%';  可以看到slow_query_log的值是OFF,mysql默认是不启用慢查询日志的。这里还有个long_query_time,默认是10秒,也就是超过了10秒即为慢查询。log_queries_not_using_indexes,如果设置为ON,则会将所有没有使用索引的查......
  • mysql 中 myisam 与 innodb 的区别?
     1.事务支持>MyISAM:强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快,但是不提供事务支持。>InnoDB:提供事务支持事务,外部键等高级数据库功能。具有事务(commit)、回滚(rollback)和崩溃修复能力(crashrecoverycapabilities)的事务安全(transaction-safe(......
  • sql server 创建复制机制
    SQLServer创建复制机制整体流程下面是创建SQLServer复制机制的整体流程,可以用表格展示步骤:步骤描述1创建发布者2创建订阅者3配置发布者4配置订阅者5启动复制具体步骤和代码示例步骤1:创建发布者首先,我们需要创建一个发布者(即主数据库),用来......
  • springboot mysql 配置 propertis
    SpringBootMySQL配置Properties在SpringBoot应用程序中,我们经常需要使用MySQL数据库来存储和检索数据。为了连接和配置MySQL数据库,我们可以使用application.properties文件。这篇文章将向您展示如何使用SpringBoot的application.properties文件来配置MySQL数据库连接。1.引......