零基础学SQL(八)——事务

SQL 事务:原理、操作与隔离机制全解析

在数据库操作中,事务是保障数据一致性的核心机制。尤其在金融转账、订单支付等关键场景,事务能避免因操作中断或错误导致的数据异常。本文将从事务定义出发,结合实操案例讲解基本操作,深入解析 ACID 特性,并梳理并发场景下的隔离级别方案。

一、事务的核心定义

事务是一组不可分割的 SQL 操作集合,它遵循 "要么全部成功,要么全部失败" 的原则。例如转账场景中,"张三账户减 1000 元" 和 "李四账户加 1000 元" 必须作为一个事务执行 ------ 若中间出现错误(如网络中断、SQL 语法错误),需撤销已执行的 "减钱" 操作,否则会导致资金凭空消失。

二、事务的基本操作与实操案例

1. 关键操作命令

操作目的 SQL 命令 说明
查看自动提交状态 SELECT @@AUTOCOMMIT; 返回 1 表示自动提交(默认),0 表示手动提交
设置自动提交方式 SET @@AUTOCOMMIT = 0; 0 为手动提交,仅对当前会话有效
提交事务 COMMIT; 确认所有操作,永久写入数据库
回滚事务 ROLLBACK; 撤销未提交的操作,恢复到事务开始前状态
手动开启事务(方式 1) START TRANSACTION; 或 BEGIN TRANSACTION; 显式开启事务,后续操作需手动提交

2. 转账场景实操对比

(1)未使用事务的风险场景

若直接执行以下 SQL,当第 2 条语句执行成功、第 3 条语句出错时,会出现 "张三钱少了但李四钱没加" 的异常:

sql 复制代码
-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三账户减1000(执行成功)
update account set money = money - 1000 where name = '张三';
-- 模拟错误(如语法错误)
update account set money = money + 1000 where name = '李四'  -- 缺少分号,执行失败
(2)使用手动提交的正确流程

通过设置@@AUTOCOMMIT = 0或START TRANSACTION开启手动事务,确保操作原子性:

sql 复制代码
-- 方式1:修改自动提交模式
SET @@AUTOCOMMIT = 0;
select * from account where name = '张三';
update account set money = money - 1000 where name = '张三';
update account set money = money + 1000 where name = '李四';
COMMIT;  -- 无错误则提交,有错误则执行ROLLBACK
-- 方式2:显式开启事务(推荐)
START TRANSACTION;
select * from account where name = '张三';
update account set money = money - 1000 where name = '张三';
update account set money = money + 1000 where name = '李四';
COMMIT;  -- 确认提交,若中间出错执行ROLLBACK撤销所有操作

三、事务的四大特性(ACID)

事务必须满足以下四个特性,才能确保数据可靠性:

  1. 原子性(Atomicity)

事务是不可分割的最小单元,如转账中的 "减钱" 和 "加钱" 要么同时完成,要么同时撤销,不存在中间状态。

  1. 一致性(Consistency)

事务执行前后,数据总量需保持一致。例如转账前两人总余额为 5000 元,事务结束后总余额仍需为 5000 元。

  1. 隔离性(Isolation)

多个事务并发执行时,每个事务的操作需与其他事务隔离,避免相互干扰(如 A 事务未提交的数据,B 事务无法读取)。

  1. 持久性(Durability)

事务一旦提交(COMMIT),对数据的修改将永久保存到数据库,即使后续系统崩溃也不会丢失。

四、并发事务的问题与隔离级别

当多个事务同时操作同一批数据时,可能出现三类问题,需通过 "隔离级别" 进行控制。

1. 并发事务的三大问题

问题类型 描述
脏读(Dirty Read) 事务 A 读取了事务 B 未提交的数据,若 B 后续回滚,A 读取的数据即为 "脏数据"。
不可重复读 事务 A 先后两次读取同一行数据,期间事务 B 修改并提交了该数据,导致 A 两次读取结果不同。
幻读(Phantom Read) 事务 A 按条件查询数据时无结果,但若尝试插入符合条件的数据,却发现该数据已存在(由事务 B 插入并提交)。

2. 四大隔离级别与问题规避

MySQL 默认隔离级别为Repeatable Read,不同级别对问题的规避能力和性能不同:

隔离级别 脏读 不可重复读 幻读 性能特点
Read uncommitted 性能最高,安全性最差
Read committed × 避免脏读,常用于 Oracle 默认
Repeatable Read(默认) × × 避免脏读和不可重复读
Serializable × × × 性能最低,安全性最高

注:"√" 表示该级别下会出现对应问题,"×" 表示不会出现。

3. 隔离级别的查看与设置

sql 复制代码
-- 查看当前会话隔离级别
SELECT @@TRANSACTION_ISOLATION;
-- 设置隔离级别(SESSION仅当前会话有效,GLOBAL对所有会话有效)
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

五、总结

事务是数据库保障数据一致性的核心机制,其 ACID 特性是衡量事务可靠性的关键标准。在实际开发中,需根据业务场景选择合适的隔离级别 ------ 例如金融场景需用Serializable确保绝对安全,而普通查询场景可用Read committed平衡性能与安全性。掌握事务的操作语法与隔离机制,是避免数据异常的重要前提。

相关推荐
秋千码途28 分钟前
一道同分排名的SQL题
数据库·sql
似水流年流不尽思念2 小时前
MySQL 的 MVCC 到底解决了幻读问题没有?请举例说明。
mysql·面试
Starry_hello world2 小时前
MySql 表的约束
数据库·笔记·mysql·有问必答
槲栎3 小时前
CentOS7中使用yum安装mysql
mysql
RestCloud3 小时前
ETLCloud中的数据转化规则是什么意思?怎么执行
数据库·数据仓库·etl
一个天蝎座 白勺 程序猿3 小时前
Apache IoTDB(4):深度解析时序数据库 IoTDB 在Kubernetes 集群中的部署与实践指南
数据库·深度学习·kubernetes·apache·时序数据库·iotdb
.Shu.4 小时前
Redis zset 渐进式rehash 实现原理、触发条件、执行流程以及数据一致性保障机制【分步源码解析】
数据库·redis·缓存
君不见,青丝成雪4 小时前
大数据技术栈 —— Redis与Kafka
数据库·redis·kafka
悟能不能悟4 小时前
排查Redis数据倾斜引发的性能瓶颈
java·数据库·redis