【MySQL】事务

devtools/2025/3/25 15:40:31/

目录

  • 基本概念
  • 事务操作
    • 自动提交事务
    • 开启事务
    • 提交事务
    • 回滚事务
    • 代码示例
  • 事务的特性 ACID
  • 事务的隔离级别
    • 读未提交 read uncommitted
    • 读已提交 read committed
    • 可重复读 repeatable read
    • 序列化(串行) serializable
    • 操作示例

基本概念

在 MySQL 中的事务(Transaction)是由存储引擎实现的,在 MySQL 中,只有 InnoDB 存储引擎才支持事务

事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行

事务用来管理 DDL、DML、DCL 操作,比如 insert,update,delete 语句,默认是自动提交的

事务操作

自动提交事务

之前的所有 SQL 操作也有事务,只是 MySQL 自动完成了,没执行一条 SQL 语句,MySQL 就自动提交事务,因此如果想要手动控制事务,就必须关闭 MySQL 的自动提交事务

语法:

set autocommit=0; -- 关闭自动提交
set autocommit=1; -- 开启自动提交

开启事务

任何一条 DML 语句(insert、update、delete)执行,标志事务的开启

语法:beginstart transaction

提交事务

成功的结束,将所有的 DML 语句操作历史记录和底层硬盘数据来一次同步

语法:commit

回滚事务

失败的结束,将所有的 DML 语句操作历史记录全部清空

语法:rollback

代码示例

create table account(id int primary key ,name varchar(20) ,money double
);
insert into account values (1,'张三',1000),(2,'李四',1000);-- 关闭自动提交
set autocommit = 0;
-- 模拟账户转账
-- 开启事务
begin;
update account set money=money-200 where name = '张三';
update account set money=money+200 where name = '李四';
-- 提交事务
commit ;

结果如下:

在这里插入图片描述

而如果只开启没提交的话,数据不会彻底落盘,虽然查询的数据变了,但是原表中的数据还没发生改变

begin;
update account set money=money-200 where name = '张三';
update account set money=money+200 where name = '李四';
select * from account;

在这里插入图片描述

这个时候回滚事务再查询数据,就会发现之前修改的操作被删除了,查询出来的数据跟原表中的数据一致

-- 回滚事务
rollback ;
select * from account;

在这里插入图片描述

事务的特性 ACID

原子性(Atomicity)
事务是不可分割的最小操作单元,要么全部执行,要么全部不执行。例如银行转账,扣钱与加钱操作必须同时成功或失败,不能只执行一半。

一致性(Consistency)
事务执行前后,数据库从一个合法状态转换到另一个合法状态。如转账前后,双方账户总金额不变。

隔离性(Isolation)
多个并发事务之间相互隔离,避免彼此干扰。根据隔离级别(如读未提交、读已提交、可重复读、串行化),控制事务间的可见性和冲突。

持久性(Durability)
事务提交后,对数据的修改会永久保存到存储介质(如磁盘),即使数据库崩溃也不丢失。

事务的隔离级别

读未提交 read uncommitted

一个事务可以读取另一个未提交事务的数据,是最低隔离级别,任何情况都无法保证,会造成脏读

脏读是数据库事务中的异常现象,指一个事务读取了另一个未提交事务修改的数据

场景示例:

  1. 事务 A 操作:执行 UPDATE account SET balance = 900 WHERE id = 1;(将账户余额改为 900 元),但未提交事务
  2. 事务 B 读取:此时事务 B 执行 SELECT balance FROM account WHERE id = 1;,读取到事务 A 未提交的 “900 元”
  3. 事务 A 回滚:若事务 A 最终回滚,数据恢复原状(如余额仍是 1000 元),则事务 B 读取的 “900 元” 从未真正生效,属于无效的 “脏数据”

影响:脏读破坏了数据一致性,事务 B 基于未最终确定的数据执行后续操作,可能导致业务逻辑错误(如错误计算余额、触发错误流程)。通过提升事务隔离级别(如使用 “读已提交”),可避免脏读问题,确保事务仅读取已提交的数据

读已提交 read committed

一个事务需等另一个事务提交后才能读取数据,可避免脏读,但会造成不可重复读

不可重复读是数据库事务中的异常现象,指同一事务内多次读取相同数据,结果却不一致,根源是其他事务在期间提交了数据修改

场景示例:

  1. 事务 A 首次查询:事务 A 执行 SELECT price FROM product WHERE id = 1;,读取商品价格为 100 元
  2. 事务 B 修改提交:事务 B 执行 UPDATE product SET price = 120 WHERE id = 1; 并提交,价格更新为 120 元
  3. 事务 A 再次查询:事务 A 再次执行相同查询,此时读到价格变为 120 元,两次结果不同

影响:该现象破坏事务一致性。如事务 A 基于首次读取的价格计算库存价值,后续因价格变动导致计算错误,影响业务逻辑正确性。通过将事务隔离级别设为 “可重复读”,可避免此问题,确保事务内读取数据始终一致

可重复读 repeatable read

在开始读取数据(事务开启)时,不再允许修改操作,可避免脏读、不可重复读,但会造成幻读

幻读是数据库事务中的一种现象,指在一个事务内,相同的查询条件多次执行查询时,由于其他事务在该期间进行了插入、删除或修改符合查询条件的数据的操作 ,导致多次查询的结果集出现差异,就好像产生了幻觉一样

场景示例:

  1. 事务 A 首次查询:银行系统中,事务 A 要批量处理余额大于 10 万元的账户,执行 SELECT account_id FROM accounts WHERE balance > 100000;,查询到 10 个符合条件的账户(如 ID 为 1-10)
  2. 事务 B 插入新账户:此时,事务 B 向系统中插入一个新账户(ID=11,余额 15 万元),并执行 INSERT INTO accounts (account_id, balance) VALUES (11, 150000); 后提交
  3. 事务 A 再次查询:事务 A 继续处理时,再次执行相同查询,结果变为 11 个账户(新增了 ID=11)

影响:幻读导致同一事务内多次相同查询的结果集不一致,使事务失去对数据的统一认知。例如,在银行账户批量处理场景中,事务 A 原本计划处理 10 个高余额账户,但因幻读多出 1 个新账户,导致实际处理范围与预期不符,破坏了事务执行的一致性。基于幻读结果的业务操作可能出现偏差。例如,电商库存管理中,事务 A 统计库存大于 50 件的商品后,因幻读导致部分商品被误判为有库存,最终引发超卖或库存统计错误,直接影响订单处理和销售策略。为避免幻读,开发人员需手动引入锁机制(如 SELECT … FOR UPDATE)或编写复杂查询逻辑,这会增加代码复杂度和维护成本。例如,在统计类任务中,可能需要额外的条件或锁来确保结果集稳定

Mysql 的默认隔离级别是 repeatable read

序列化(串行) serializable

最高事务隔离级别,事务串行化顺序执行,可避免脏读、不可重复读与幻读。但该级别效率低下,耗数据库性能,一般不使用

事务隔离级别脏读不可重复读幻读
读未提交 read uncommitted
读已提交 read committed×
可重复读 repeatable read××
序列化(串行) serializable×××

操作示例

-- 查看隔离级别  
show variables like '%isolation%';  -- 设置隔离级别  
/*  
set session transaction isolation level 级别字符串  
级别字符串:read uncommitted、read committed、repeatable read、serializable  
*/  
-- 设置read uncommitted  
set session transaction isolation level read uncommitted;  -- 设置read committed  
set session transaction isolation level read committed;  -- 设置repeatable read  
set session transaction isolation level repeatable read;  -- 设置serializable  
set session transaction isolation level serializable;

http://www.ppmy.cn/devtools/170592.html

相关文章

SQL 通配符

SQL 通配符 在SQL查询中,通配符是一种非常有用的特性,它允许用户在查询时使用特殊字符来匹配一系列的值。本文将详细介绍SQL中的通配符及其用法,帮助读者更好地理解如何在SQL查询中使用通配符。 1. 什么是通配符? 通配符是SQL查…

PRODIGY: “不折腾人”的蛋白-蛋白/蛋白-小分子结合能计算工具

PRODIGY(全称为 PROtein binDIng enerGY prediction)是一种蛋白质结合能预测工具,可利用蛋白质-蛋白质复合物的三维结构来预测其结合亲和力。PRODIGY 利用一种高效的基于接触的方法,在估计结合自由能和解离常数的同时,…

建筑安全员考试:“高效记忆” 关键词引领的学习捷径

建筑安全员考试需要记忆大量的知识点,如何高效记忆成为考生关注的焦点。运用 “高效记忆” 相关关键词,能帮助考生找到学习的捷径。​ 利用 “口诀记忆法” 关键词,将复杂的知识点编成口诀。例如,在记忆安全色与安全标志时&#…

使用 ncurses 库创建文本用户界面:基础函数详解

简介 ncurses 是一个功能强大的库,用于在 Unix-like 系统中创建文本用户界面。它提供了丰富的函数来控制屏幕上的文本显示、处理键盘输入、绘制图形元素等。本文将详细介绍 ncurses 库中的一些基础函数,包括 printw、wrefresh、获取用户信息、键盘输入、…

ubuntu桌面图标异常——主目录下的所有文件(如文档、下载等)全部显示在桌面

ubuntu桌面图标异常 问题现象问题根源系统级解决方案方法一:全局修改(推荐多用户环境)方法二:单用户修改(推荐个人环境)操作验证与调试避坑指南扩展知识参考文档问题现象 主目录文件异常显示 用户主目录(如/home/user/)下的所有文件(如文档、下载等)全部显示在桌面,…

css white-space: pre-line; 用处大

1.normal:忽略多余的空白,只保留一个空白(默认); 2.pre:保留空白(行为方式类似于html中的pre标签); 3.nowrap:只保留一个空白,文本不会换行,会在在同一行上继续,直到遇到br标签为止。…

DAPO:一个开源的大规模大型语言模型LLM强化学习系统

推断扩展赋予了大型语言模型前所未有的推理能力,强化学习作为激发复杂推理的核心技术,清华大学联合字节提出了解耦片段与动态采样策略优化(DAPO)算法,并全面开源了一个最先进的大规模强化学习系统,该系统使用Qwen2.5-32B基础模型在AIME 2024上取得了50分的高分。还开源了…

(滑动窗口)算法训练篇11--力扣3.无重复字符的最长字串(难度中等)

目录 1.题目链接:3.无重复字符的最长字符 2.题目描述: 3.解法(滑动窗口): 1.题目链接:3.无重复字符的最长字符 2.题目描述: 给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。 示例…