MySQL的事务机制

事务

事务概念:事务是一个完整的操作单元,不可分割,事务中的操作要么全部成功,要么全部失败。

1. 事务特性

ACID

1.1 原子性(A)

一个事务中所有操作是不能被分割的,要么所有的操作都成功,要么都失败

1.2 一致性(C)

事务开始前到事务结束后,数据总量保持不变的

  • 示例

    • 转账

      jack 钱数 kucy 钱数 总钱数
      开始前 jack:200 lucy:200 400
      结束后 jack:100 lucy:300 400
    • 买书

      书本数量 单价 存款
      开始前 2 100 300
      结束后 1 100 200

1.3 隔离性(I)

两个不同的事务之间是隔离的,互不影响

1.4 持久性(D)

事务一旦提交,数据永久保存磁盘上

2. 隔离级别【不同隔离级别产生的问题】

2.1 读未提交

read uncommitted

会出现脏读、幻读、不可重复读。

脏读:一个事务读到了另一个事务没有提交的数据

例如:A 欠 B 300元

还钱流程:

  1. A、B 开启事务
  2. B 查询余额,1000
  3. A 开始向 B 转账,A 打电话给 B,说我把钱转给你了,你看看
  4. B 再查询余额,1300,跟 A 说,是的,我收到了
  5. A 执行了 rollback
  6. B 再查余额,1000,因为 A 回滚了操作

2.2 读已提交

read committed :oracle 默认

只解决了脏读,会出现幻读及不可重复读。

不可重复读:在同一个事务中,连续两次读取到的数据不一致

2.3 可重复读

repeatable read :mysql 默认

只会出现幻读(对于增加)

  • A 事务执行查询,查到 3 条数据

  • B 事务插入一条数据,并提交

  • A 事务执行了更新,发现更新的数量是 4 条,感觉像出现了幻觉

幻读处理:可重复读隔离级别在一定程度上解决了幻读问题,但并非完全避免。它主要通过以下机制来减少幻读的可能性:

  1. 快照读:对于普通的 SELECT 查询,MySQL 使用多版本并发控制(MVCC)来提供一个数据的一致性快照。事务在执行第一个查询操作时会创建一个一致性视图(Read View),之后的查询都会基于这个视图进行。这意味着即使其他事务在此期间插入了新记录,当前事务也无法看到这些新记录,从而避免了幻读(在大多数情况下)。
  2. 当前读:对于需要修改数据的操作(如 INSERT、UPDATE、DELETE)或使用锁定读(如 SELECT ... FOR UPDATE),MySQL 使用 Next-Key Locking 机制。这是一种特殊的锁,它包括了记录锁和间隙锁,可以防止其他事务在已锁定的记录附近插入新记录,从而进一步减少幻读的可能性。
  3. 然而,即使在可重复读隔离级别下,幻读在某些特定场景下仍然可能发生。例如,当事务在更新记录时改变了记录的隐藏 trx_id 值,或者其他事务在间隙锁的范围内插入了新记录时,就可能出现幻读。

2.4 串行化

Serializable

不会有任何问题。相当于锁表,效率极低

2.5 实际开发会用到的隔离级别

  1. read committed :oracle默认

    缺点:不可重复读

  2. repeatable read :mysql 默认

扩展:read committed 已经可以解决大部分问题,为什么 MySQL 的默认隔离级别还会设置成 repeatable read

  1. 可重复读
  2. SELECT @@transaction_isolation;

3. MVCC

MVCC 是数据库中一种保证并发性与数据安全性的思想

3.1 生效时间

只有在数据事务隔离级别是读已提交或者可重复读时生效

  1. 读是从缓存中拿数据
    • 第一次查询时,查询表,获取数据,写入数据库缓存
    • 后期的查询,只要是缓存中有的数据,直接查缓存,不查询表。以此来保证并发性
  2. 写的时候会把数据库把最新的数据同步到缓存
    • 保证安全性

3.2 使用三种日志

  1. Undolog 日志:在执行更新语句之前,需要先将旧的数据拷贝到 Undo Log 中。Undo 日志在事务提交或回滚的时候用于还原数据。
  2. Redo 日志:当事务提交时,MySQL 会将事务修改写入到 Redo Log 中。如果 MySQL 突然崩溃并且缓存数据不能恢复,Redo 日志就可以帮助 MySQL 恢复数据。
  3. Binlog 日志:Binlog 日志主要用于主从复制。当从库需要和主库数据保持一致时,需要从主库中读取 Binlog 的数据进行同步。

在执行插入、更新和删除操作时,MySQL 需要进行两个操作。第一个操作是将旧数据的快照保存到 Undolog 日志中。第二个操作是将新的数据记录到 InnoDB 表空间中,并同时将新数据的变更写入到 Redolog 日志和 Binlog 日志中。当事务提交时,MySQL 只有收到了所有三种类型的日志都写入成功的信号,才会返回成功事务提交的响应。这就实现了 MySQL 的 ACID 事务的特性。

相关推荐
ii_best4 小时前
按键精灵支持安卓14、15系统,兼容64位环境开发辅助工具
android
美狐美颜sdk5 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
DCTANT7 小时前
【原创】国产化适配-全量迁移MySQL数据到OpenGauss数据库
java·数据库·spring boot·mysql·opengauss
程序员岳焱9 小时前
Java 与 MySQL 性能优化:MySQL全文检索查询优化实践
后端·mysql·性能优化
恋猫de小郭9 小时前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin
喜欢敲代码的程序员9 小时前
SpringBoot+Mybatis+MySQL+Vue+ElementUI前后端分离版:项目搭建(一)
spring boot·mysql·elementui·vue·mybatis
aqi0010 小时前
FFmpeg开发笔记(七十七)Android的开源音视频剪辑框架RxFFmpeg
android·ffmpeg·音视频·流媒体
钢铁男儿10 小时前
C# 委托(调用带引用参数的委托)
java·mysql·c#
叁沐10 小时前
MySQL 02 日志系统:一条SQL更新语句是如何执行的?
mysql
RunsenLIu10 小时前
基于Vue.js + Node.js + MySQL实现的图书销售管理系统
vue.js·mysql·node.js