[MySQL初阶]MySQL(9)事务机制

标题:[MySQL初阶]MySQL(9)事物机制
@水墨不写bug

在这里插入图片描述


文章目录

  • 一、认识事务
    • 1、多线程访问数据库出现的问题
    • 2、对CURD的限制是通过事务机制实现的
    • 3、事务的四个属性
    • 4、哪些引擎支持事务
  • 二、事务的提交与autocommit设置
  • 三、事务的隔离性和隔离级别
    • (1) 查看当前隔离级别
    • (2) 设置隔离级别
    • (3) 事务隔离级别的作用
    • (4)MySQL InnoDB 的四种隔离级别
      • (1) 读未提交(Read Uncommitted)
      • (2) 读已提交(Read Committed)
      • (3) 可重复读(Repeatable Read)
      • (4) 串行化(Serializable)
    • (5)各隔离级别对比表
  • 四、事务的一致性
      • 1. AID 特性与一致性的关系
        • (1) 原子性(Atomicity)
        • (2) 隔离性(Isolation)
        • (3) 持久性(Durability)
        • (4) 应用层逻辑(用户的配合)


一、认识事务

1、多线程访问数据库出现的问题

MySQL是一款网络服务,那么必定有多个客户端同时访问服务器的场景出现:假如有一个抢票系统,有两个客户端抢票,一个客户端抢票之后,数据库还没有及时更新,这张票又被另一个客户端抢了一次,一张票被卖了两次。这不符合逻辑!
于是,必须要对数据库的CURD操作进行一定的限制,才能解决上面的问题。

2、对CURD的限制是通过事务机制实现的

事务就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。
事务主要用于处理操作量大,复杂度高的数据。比如要删除一个被开除的员工的所有历史信息以及和他相关的信息,就需要多条 MySQL 语句构成,那么所有这些操作合起来,就构成了一个事务。

但是要知道,同一时刻并不是只有一个事务在运行,而是有多个事务同时在运行。如果大量的事务在不加保护的情况下访问同一个表数据,就一定会出现问题。因为事务由多条sql语句组成,一个事务执行了一半,突然mysql客户端挂了,那么这执行了一半的事务该怎么处理?

3、事务的四个属性

于是,MySQL规定,一个完整的事务,不仅仅是简单的sql语句的组合,还要满足下面的四个属性

原子性(Atomicity,或称不可分割性): 一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误(导致客户端挂了),执行了一半的事务会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性(Consistency): 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
隔离性(Isolation,又称独立性): 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交( Read uncommitted )、读提交( read committed )、可重复读( repeatable read )和串行化( Serializable )。
持久性(Durability): 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

此外,事务本质上是为应用层服务的。因为我们并不是直接访问数据库的,而是通过上层的各种语言来范围访问数据库的,于是多条sql语句封装出来的事务可以简化上层的编程模型和逻辑。

4、哪些引擎支持事务

使用指令查询:

mysql> show engines\G;
*************************** 1. row ***************************Engine: ndbclusterSupport: NOComment: Clustered, fault-tolerant tables
Transactions: NULLXA: NULLSavepoints: NULL
*************************** 2. row ***************************Engine: MEMORYSupport: YESComment: Hash based, stored in memory, useful for temporary tables
Transactions: NOXA: NOSavepoints: NO
*************************** 3. row ***************************Engine: InnoDBSupport: DEFAULTComment: Supports transactions, row-level locking, and foreign keys
Transactions: YESXA: YESSavepoints: YES
*************************** 4. row ***************************Engine: PERFORMANCE_SCHEMASupport: YESComment: Performance Schema
Transactions: NOXA: NOSavepoints: NO
*************************** 5. row ***************************Engine: MyISAMSupport: YESComment: MyISAM storage engine
Transactions: NOXA: NOSavepoints: NO
*************************** 6. row ***************************Engine: FEDERATEDSupport: NOComment: Federated MySQL storage engine
Transactions: NULLXA: NULLSavepoints: NULL
*************************** 7. row ***************************Engine: ndbinfoSupport: NOComment: MySQL Cluster system information storage engine
Transactions: NULLXA: NULLSavepoints: NULL
*************************** 8. row ***************************Engine: MRG_MYISAMSupport: YESComment: Collection of identical MyISAM tables
Transactions: NOXA: NOSavepoints: NO
*************************** 9. row ***************************Engine: BLACKHOLESupport: YESComment: /dev/null storage engine (anything you write to it disappears)
Transactions: NOXA: NOSavepoints: NO
*************************** 10. row ***************************Engine: CSVSupport: YESComment: CSV storage engine
Transactions: NOXA: NOSavepoints: NO
*************************** 11. row ***************************Engine: ARCHIVESupport: YESComment: Archive storage engine
Transactions: NOXA: NOSavepoints: NO
11 rows in set (0.01 sec)

从查询结果可知,目前只有InnodeDB引擎支持事务机制


二、事务的提交与autocommit设置

事务的提交(commit)方式有两种:
自动提交;
手动提交;
autocommit变量是设置是否自动提交。
查看autocommit变量:

show variables like 'autocommit';

设置是否自动提交:

SET AUTOCOMMIT=1; #SET AUTOCOMMIT=1 开启自动提交
SET AUTOCOMMIT=0; #SET AUTOCOMMIT=0 禁止自动提交

当我们想要开始一个事务,需要指令:

begin;
#或者
start transaction;

当我们想要提交一个事务,需要指令:

commit;

而这两个指令之间的sql语句就是事务的内容。


为了方便后面的演示,这里我们创建一个表结构如下:

create table if not exists account(id int primary key,name varchar(50) not null default '',blance decimal(10,2) not null default 0.0)ENGINE=InnoDB DEFAULT CHARSET=UTF8;

此时暂时把全局隔离级别设置为读未提交【为了方便通过另一个客户端查看表中的数据】:

set global transaction isolation level READ UNCOMMITTED;

查看隔离级别:

SELECT @@global.transaction_isolation AS '全局隔离级别', @@session.transaction_isolation AS '当前会话隔离级别';

重启mysql,同步当前会话和全局的隔离级别,然后查看:
在这里插入图片描述

  • 特性一:如果事务通过begin/start transation方式开始,则必须通过commit提交,这样才会持久化,与是否设置autocommit无关(默认情况下autocommit是ON打开的,至于具体有什么用,在后文会讲)。

如果有两个客户端同时访问同一张表,同时启动了两个事务,一个客户端事务执行了一半,崩溃了,MySQL会自动回滚


什么是回滚?
当我们开始一个事务之后,在事务执行的过程中,可以创建保存点,这个保存点可以理解为游戏中的存档点,如果对于最新的操作不满意,可以回滚(读取存档点):

savepoint s1; #创建一个保存点s1

首先,通过begin;开启一个事务。
然后,我们在已经创建的表中插入数据:
在这里插入图片描述
此时设置一个savepoint s1;
在这里插入图片描述
然后再次进行一些增删改操作(比如新插入一条数据):
在这里插入图片描述
但是发现在新进行的操作出错了,不想要了,于是可以回滚(读取存档点s1):

rollback to s1;

结果:
在这里插入图片描述
于是,新插入的一条“haha”的数据就被删除了。这就是回滚


回到特性一的演示:
证明:未commit,客户端崩溃,MySQL自动会回滚[因为通过手动开始,autocommit不会自动提交]
启动两个事务,左侧插入一个新数据lisi,右侧可以看到新插入的数据:

在这里插入图片描述
左侧事务的客户端被ctrl+\ 被发送abort信号,进程被杀死,右侧客户端发现新插入的lisi被MySQL自动回滚了。
在这里插入图片描述

证明:commit了,客户端崩溃,MySQL数据不会再受影响,已经持久化。[因为通过手动开始,autocommit不会自动提交]

启动两个事务,左侧客户端插入数据jimmay,commit之后被信号杀死,右侧查询可以找到新插入的数据:
在这里插入图片描述

证明:没有手动通过begin;/start transaction;启动一个事务,autocommit会对提交产生影响。

在autocommit=1;(开启)的情况下:
对于没有手动通过begin;/start transaction;启动一个事务,一条sql语句就是一个事务,因为每一条语句都会被包装为一个事务。
即使一条语句被执行后,客户端直接崩溃,语句仍然被持久化:
在这里插入图片描述
在autocommit=0;(开启)的情况下:
需要手动commit,无论执行了多少操作,如果在客户端退出之前没有commit,则所有的操作都会被回滚:
在这里插入图片描述
如果commit了,做的操作就会被持久化:
在这里插入图片描述


到这里,我们可以总结一下:

  • 事务开始是用begin/start transaction,需要手动commit提交,才会持久化,不收到autocommit设置的影响。
  • 事务可以通过设置savepoint手动回滚;当操作异常时,MySQL会自动回滚。
  • InnoDB 每一条 SQL 语言都默认封装成事务自动提交。(select有特殊情况,因为MySQL 有 MVCC )。
  • 从上面的演示,我们能看到事务本身的原子性(回滚),持久性(commit)。

从哪里体现隔离性?


三、事务的隔离性和隔离级别

数据库中,为了保证事务执行过程中尽量不受干扰,就有了一个重要特征:隔离性
数据库中,允许事务受不同程度的干扰,就有了一种重要特征:隔离级别

(1) 查看当前隔离级别

SHOW VARIABLES LIKE 'transaction_isolation';
-- 输出示例:transaction_isolation = REPEATABLE-READ

(2) 设置隔离级别

-- 全局设置(重启后生效)
SET GLOBAL TRANSACTION ISOLATION LEVEL+隔离登记;
-- 当前会话设置
SET SESSION TRANSACTION ISOLATION LEVEL+隔离登记;

MySQL InnoDB 存储引擎支持四种标准的事务隔离级别,它们通过不同的锁机制多版本并发控制(MVCC) 实现事务之间的数据可见性和并发控制。


(3) 事务隔离级别的作用

事务隔离级别定义了多个并发事务之间的数据可见性规则,核心目标是解决以下问题:

  • 脏读(Dirty Read):读到其他事务未提交的数据。
  • 不可重复读(Non-Repeatable Read):同一事务中多次读取同一数据,结果不一致(其他事务修改了该行)。
  • 幻读(Phantom Read):在同一事务中,由于其他事务插入或删除了符合查询条件的行,导致多次相同查询的结果集行数不一致。

(4)MySQL InnoDB 的四种隔离级别

按隔离级别从低到高排序:

(1) 读未提交(Read Uncommitted)

  • 特点:所有的事务都可以看到其他事务没有提交的
    执行结果(可能读到“脏数据”)相当于没有任何隔离性。
  • 问题:存在 脏读、不可重复读、幻读
  • 实现方式:几乎不加锁,依赖最低限度的锁机制。
  • 使用场景:极少使用,仅在需要最高并发且不关心数据一致性的场景。

(2) 读已提交(Read Committed)

  • 特点:一个事务只能看到其他的已经提交的事务所做的改变。
  • 解决的问题:避免脏读。
  • 遗留问题:存在 不可重复读、幻读
  • 实现方式
    • 锁机制:使用 行级锁(Record Locks),写操作锁定当前行。
    • MVCC:每次 SELECT 生成一个独立的快照(一致性视图),基于当前已提交的数据。
  • 使用场景:适用于大多数 OLTP 系统(如 Oracle 默认级别)。

(3) 可重复读(Repeatable Read)

  • 特点: MySQL 默认的隔离级别,同一事务中多次读取同一数据的结果一致。
  • 解决的问题:避免脏读、不可重复读。
  • 遗留问题:仍可能发生 幻读(但 InnoDB 通过 间隙锁 基本消除)。
  • 实现方式
    • 锁机制:使用 记录锁(Record Locks) + 间隙锁(Gap Locks)(合称 临键锁 Next-Key Locks)。
    • MVCC:事务首次 SELECT 生成一致性视图,后续读取沿用该视图。
  • 默认级别:InnoDB 的默认隔离级别。
  • 幻读的解决
    -- 事务A
    BEGIN;
    SELECT * FROM users WHERE age > 20; -- 假设返回3条记录-- 事务B
    INSERT INTO users (id, age) VALUES (4, 25); -- 提交-- 事务A再次查询
    SELECT * FROM users WHERE age > 20; -- 在可重复读下,仍然返回3条记录(避免幻读)
    

(4) 串行化(Serializable)

  • 特点:事务的最高隔离级别,所有事务串行执行,完全隔离。
  • 解决的问题:避免脏读、不可重复读、幻读。
  • 实现方式
    • 锁机制:所有 SELECT 自动转换为 SELECT ... FOR SHARE,使用共享锁,导致读写冲突时阻塞。
    • MVCC:基本失效,强制串行化。
  • 使用场景:对数据一致性要求极高,但性能极低,很少使用。

(5)各隔离级别对比表

隔离级别脏读不可重复读幻读锁机制性能
读未提交可能可能可能行级写锁最高
读已提交可能可能行级写锁 + MVCC
可重复读(InnodeDB默认)无*临键锁 + MVCC中等
串行化表级锁或严格的行级锁最低

*InnoDB 在可重复读级别下通过间隙锁基本消除幻读。


四、事务的一致性

事务的 一致性(Consistency) 需要 原子性(Atomicity)隔离性(Isolation)持久性(Durability) 以及 应用层的正确逻辑(用户的配合) 共同维护。


1. AID 特性与一致性的关系

事务的 ACID 特性中,一致性(Consistency)是最终目标,而其他三个特性(原子性、隔离性、持久性)是实现一致性的技术手段。同时,应用层逻辑(用户代码)的合理设计是确保一致性的必要条件。

(1) 原子性(Atomicity)
  • 作用:事务内的操作要么全部成功,要么全部失败回滚。
  • 对一致性的贡献:防止部分操作失败导致数据处于“半完成”状态。
    -- 示例:转账操作(原子性保证)
    BEGIN;
    UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;  -- 扣款
    UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;  -- 入账
    COMMIT; -- 若任何一步失败,整个事务回滚,避免数据不一致。
    
(2) 隔离性(Isolation)
  • 作用:控制并发事务之间的相互影响。
  • 对一致性的贡献:防止脏读、不可重复读、幻读等问题破坏数据逻辑。
    -- 示例:隔离级别避免中间状态暴露
    SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    BEGIN;
    SELECT balance FROM accounts WHERE user_id = 1;  -- 基于快照的一致性视图
    -- 其他事务的修改不会影响当前事务的查询结果
    COMMIT;
    
(3) 持久性(Durability)
  • 作用:事务提交后,修改必须永久保存到存储介质(如磁盘)。
  • 对一致性的贡献:确保提交后的数据在故障后仍可恢复,避免数据丢失导致不一致。
    -- 提交后数据写入磁盘(通过 Redo Log 等机制保证)
    COMMIT;
    
(4) 应用层逻辑(用户的配合)
  • 作用:开发者需确保业务规则被正确编码。
  • 对一致性的贡献:数据库无法自动理解业务规则,需通过代码显式维护。
    -- 示例:应用层必须检查转账的用户减去金额,转到的用户加上相应的金额。
    BEGIN;
    UPDATE accounts SET balance = balance - amount WHERE user_id = 1;
    UPDATE accounts SET balance = balance + amount WHERE user_id = 2;
    COMMIT;
    

完~
转载请注明出处

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/74721.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring-cloud-alibaba-nacos-config使用说明

一、核心功能与定位 Spring Cloud Alibaba Nacos Config 是 Spring Cloud Alibaba 生态中的核心组件之一,专为微服务架构提供动态配置管理能力。它通过整合 Nacos 的配置中心功能,替代传统的 Spring Cloud Config,提供更高效的配置集中化管理…

SonarQube数据库配置

SonarQube部署完成后,在浏览器地址栏输入http://IP:9000可以进入登录页面,以本机运行为例,地址为http://127.0.0.1:9000/,默认登录名:admin,登录密码也是admin。登录后会要求设置密码: 按要求设…

医药档案区块链系统

1. 医生用户模块​​ ​​目标用户​​:医护人员 ​​核心功能​​: ​​检索档案​​:通过关键词或筛选条件快速定位患者健康档案。​​请求授权​​:向个人用户发起档案访问权限申请,需经对方确认。​​查看档案​…

CSS3学习教程,从入门到精通, 化妆品网站 HTML5 + CSS3 完整项目(26)

化妆品网站 HTML5 CSS3 完整项目 下面是一个完整的化妆品网站项目,包含主页、登录页面和注册页面。我将按照您的要求提供详细的代码和注释。 1. 网站规划与需求分析 需求分析 展示化妆品产品信息提供用户注册和登录功能响应式设计,适配不同设备美观…

ROS2 多机时间同步(Chrony配置简明指南)

适用场景: 主机运行 ROS2 Humble(发布 /scan 等),板子运行 ROS2 Foxy(发布 /tf 等),两边通过 ROS_DOMAIN_ID 跨平台通讯。需要保证系统时间对齐,避免 TF 插值失败、建图抖动等问题。…

Nginx配置伪静态,URL重写

Nginx配置伪静态,URL重写 [ Nginx ] 在Nginx低版本中,是不支持PATHINFO的,但是可以通过在Nginx.conf中配置转发规则实现: location / { // …..省略部分代码if (!-e $request_filename) {rewrite ^(.*)$ /index.php?s/$1 l…

电路笔记(元器件):ADC LTC系列模数转换器的输出范围+满量程和偏移调整

LTC1740(LTC1740官方文档)是Analog Devices(原Linear Technology)公司生产的一款高性能、低功耗的14位模数转换器(ADC)。它通常用于需要高精度和快速采样率的应用中,如通信系统、数据采集设备等。同类产品 LTC1746:一款14位、40Ms…

续-算法-数学知识

3、欧拉函数 1、定义: 1~n 中与 n 互质的数的个数 例如:6 的有 1 2 3 4 5 6 其中,与 n 互质 的 数的个数为 2个分别是:1、5 2、计算: $ N p_1^{a1} p_2^{a2} p_3^{a3} … p_k^{ak} $(例如&#x…

C/C++测试框架googletest使用示例

文章目录 文档编译安装示例参考文章 文档 https://github.com/google/googletest https://google.github.io/googletest/ 编译安装 googletest是cmake项目,可以用cmake指令编译 cmake -B build && cmake --build build将编译产物lib和include 两个文件夹…

LintCode第974题-求矩阵各节点的最短路径(以0为标准)

描述 给定一个由0和1组成的矩阵,求每个单元格最近的0的距离。 两个相邻细胞之间的距离是1。 给定矩阵的元素数不超过10,000。 在给定的矩阵中至少有一个0。 单元格在四个方向上相邻:上,下,左和右。 样例 例1: 输入: [[0,0,0],[0,0,0],[0…

Redis核心机制-缓存、分布式锁

目录 缓存 缓存更新策略 定期生成 实时生成 缓存问题 缓存预热(Cache preheating) 缓存穿透(Cache penetration) 缓存雪崩(Cache avalanche) 缓存击穿(Cache breakdown) 分…

CF每日5题(1300-1500)

最近急速补练蓝桥杯中,疏于cf练习。 感觉自己过题还是太慢了。 今日水题,我水水水水。 1- 1979C lcm 水 1400 第 i i i局赢了,1个硬币顶 k [ i ] k[i] k[i]个贡献,所以每局分硬币 x i 1 k [ i ] x_i{1\over k[i]} xi​k[i]1​个…

从代码学习深度学习 - LSTM PyTorch版

文章目录 前言一、数据加载与预处理1.1 代码实现1.2 功能解析二、LSTM介绍2.1 LSTM原理2.2 模型定义代码解析三、训练与预测3.1 训练逻辑代码解析3.2 可视化工具功能解析功能结果总结前言 深度学习中的循环神经网络(RNN)及其变种长短期记忆网络(LSTM)在处理序列数据(如文…

easy-poi 一对多导出

1. 需求: 某一列上下两行单元格A,B值一样且这两个单元格, 前面所有列对应单元格值一样的话, 就对A,B 两个单元格进行纵向合并单元格 1. 核心思路: 先对数据集的国家,省份,城市...... id 身份证进行排序…

AI比人脑更强,因为被植入思维模型【42】思维投影思维模型

giszz的理解:本质和外在。我们的行为举止,都是我们的内心的表现。从外边可以看内心,从内心可以判断外在。曾国藩有7个识人的方法,大部分的人在他的面前如同没穿衣服一样。对于我们自身的启迪,我认为有四点&…

Spring Boot 打印日志

1.通过slf4j包中的logger对象打印日志 Spring Boot内置了日志框架slf4j,在程序中调用slf4j来输出日志 通过创建logger对象打印日志,Logger 对象是属于 org.slf4j 包下的不要导错包。 2.日志级别 日志级别从高到低依次为: FATAL:致命信息,表…

【IOS webview】源代码映射错误,页面卡住不动

报错场景 safari页面报源代码映射错误,页面卡住不动。 机型:IOS13 技术栈:react 其他IOS也会报错,但不影响页面显示。 debug webpack配置不要GENERATE_SOURCEMAP。 解决方法: GENERATE_SOURCEMAPfalse react-app…

ES中经纬度查询geo_point

0. ES版本 6.x版本 1. 创建索引 PUT /location {"settings": {"number_of_shards": 1,"number_of_replicas": 0},"mappings": {"location": {"properties": {"id": {"type": "keywor…

OpenCV界面编程

《OpenCV计算机视觉开发实践:基于Python(人工智能技术丛书)》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 OpenCV的Python开发环境搭建(Windows)-CSDN博客 OpenCV也支持有限的界面编程,主要是针对窗口、控件和鼠标…

GOC L2 第五课模运算和周期二

课堂回顾: 求取余数的过程叫做模运算 每轮的动作都是重复的,我们称这个过程位周期。 课堂学习: 剩余计算器 秋天到了,学校里的苹果熟了,太乙老师,想让哪吒帮忙设计一个计算器,看每个小朋友能分…