零基础学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平衡性能与安全性。掌握事务的操作语法与隔离机制,是避免数据异常的重要前提。

相关推荐
Joseit1 小时前
AI应用生成平台:数据库、缓存与存储
数据库·人工智能·缓存
迎風吹頭髮3 小时前
UNIX下C语言编程与实践9-UNIX 动态库创建实战:gcc 参数 -fpic、-shared 的作用与动态库生成步骤
c语言·数据库·unix
程序视点3 小时前
MySQL COUNT(*)性能对比:MyISAM为何比InnoDB快?全面解析与优化方案
mysql
黑马金牌编程4 小时前
深入浅出 Redis:从核心原理到运维实战指南一
数据库·redis·缓存·性能优化·非关系型数据库
李迟4 小时前
2025年9月个人工作生活总结
服务器·数据库·生活
野犬寒鸦6 小时前
从零起步学习Redis || 第四章:Cache Aside Pattern(旁路缓存模式)以及优化策略
java·数据库·redis·后端·spring·缓存
茉莉玫瑰花茶7 小时前
Redis - Bitfield 类型
数据库·redis·缓存
lang201509287 小时前
MySQL InnoDB备份恢复全指南
数据库·mysql
爱吃香蕉的阿豪8 小时前
.NET Core 中 System.Text.Json 与 Newtonsoft.Json 深度对比:用法、性能与场景选型
数据库·json·.netcore
mpHH8 小时前
postgresql中的默认列
数据库·postgresql