MYSQL——基础知识(SQL事务)

目录

前言

一、事务是什么?

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

[三、MySQL 事务控制语句](#三、MySQL 事务控制语句)

四、实战案例:安全转账

[五、事务隔离级别(Isolation Levels)](#五、事务隔离级别(Isolation Levels))

六、自动提交模式(AUTOCOMMIT)

七、事务使用注意事项

八、总结:事务使用口诀


前言

在现代数据库系统中,事务(Transaction) 是保障数据一致性和完整性的核心机制。无论是银行转账、订单支付,还是用户注册,背后都离不开事务的支撑。

想象这样一个场景:

张三向李四转账 100 元

这需要两步操作:

  1. 张三账户余额减 100;
  2. 李四账户余额加 100。

如果第一步成功,第二步因系统崩溃失败,就会导致资金凭空消失

MySQL 事务 正是解决此类问题的"安全锁"------它确保这两步要么全部成功,要么全部失败

本文将深入讲解 MySQL 事务的原理、ACID 特性、控制语句、隔离级别及最佳实践。


一、事务是什么?

事务的定义

事务是一组 SQL 操作的逻辑单元,这些操作被视为一个整体:

  • 全部执行成功 → 提交(COMMIT),永久生效;
  • 任一操作失败 → 回滚(ROLLBACK),全部撤销。

重要前提

只有 InnoDB 存储引擎支持事务

MyISAM、MEMORY 等引擎不支持事务,操作会自动提交。


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

特性 英文 说明 示例
原子性 Atomicity 操作不可分割,全做或全不做 转账两步必须同时成功或失败
一致性 Consistency 事务前后数据符合业务规则 转账后总金额不变(1000 → 900+100)
隔离性 Isolation 并发事务互不干扰 A 查余额时,B 的未提交转账不可见
持久性 Durability 提交后修改永久保存 即使断电,已提交的转账不会丢失

ACID 是事务的"黄金标准",缺一不可。


三、MySQL 事务控制语句

1. 开启事务

sql 复制代码
-- 方法1:显式开启
START TRANSACTION;
-- 或
BEGIN;

-- 方法2:关闭自动提交
SET AUTOCOMMIT = 0;  -- 之后每条 DML 都属于事务,需手动 COMMIT/ROLLBACK

📌 默认行为 :MySQL 默认 AUTOCOMMIT=1,即每条 INSERT/UPDATE/DELETE 自动提交!


2. 提交与回滚

sql 复制代码
-- 提交:永久保存更改
COMMIT;

-- 回滚:撤销所有未提交的更改
ROLLBACK;

3. 保存点(Savepoint)------ 事务中的"检查点"

sql 复制代码
START TRANSACTION;

UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
SAVEPOINT before_transfer;  -- 设置保存点

UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;

-- 若第二步出错,可回滚到保存点
ROLLBACK TO before_transfer;

-- 最终决定提交或完全回滚
COMMIT;  -- 或 ROLLBACK;

优势:实现事务内的"部分回滚",提升灵活性。


四、实战案例:安全转账

sql 复制代码
-- 开启事务
START TRANSACTION;

-- 扣款
UPDATE accounts 
SET balance = balance - 100 
WHERE user_id = 1 AND balance >= 100;

-- 检查扣款是否成功(防止余额不足)
IF ROW_COUNT() = 0 THEN
    ROLLBACK;
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '余额不足';
END IF;

-- 入账
UPDATE accounts 
SET balance = balance + 100 
WHERE user_id = 2;

-- 提交
COMMIT;

关键点

  • 使用 ROW_COUNT() 验证操作是否生效;
  • 通过 SIGNAL 抛出错误终止流程(需在存储过程中使用)。

五、事务隔离级别(Isolation Levels)

并发事务可能引发三大问题:

问题 描述 隔离级别解决情况
脏读(Dirty Read) 读到其他事务未提交的数据 READ COMMITTED 及以上解决
不可重复读(Non-repeatable Read) 同一事务内多次读取结果不同 REPEATABLE READ 及以上解决
幻读(Phantom Read) 同一查询返回新插入的行 SERIALIZABLE 解决

MySQL 支持的四种隔离级别

隔离级别(Isolation Level) 脏读(Dirty Read) 不可重复读(Non-repeatable Read) 幻读(Phantom Read) 性能表现
READ UNCOMMITTED 允许 允许 允许 最高
READ COMMITTED 禁止 允许 允许 较高
REPEATABLE READ(MySQL 默认) 禁止 禁止 InnoDB 通过 MVCC 解决 中等
SERIALIZABLE 禁止 禁止 禁止 最低(串行执行)

查看与设置隔离级别

复制代码
-- 查看当前会话隔离级别
SELECT @@transaction_isolation;

-- 设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- 设置全局(影响新连接)
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

InnoDB 的优化

REPEATABLE READ 下,InnoDB 通过 MVCC(多版本并发控制)Next-Key Lock 有效避免幻读,因此通常无需升级到 SERIALIZABLE


六、自动提交模式(AUTOCOMMIT)

模式 行为 适用场景
AUTOCOMMIT=1(默认) 每条 DML 自动提交 简单脚本、交互式查询
AUTOCOMMIT=0 需手动 COMMIT/ROLLBACK 应用程序、复杂业务逻辑

在应用程序中使用

php 复制代码
<?php
$pdo = new PDO("mysql:host=localhost;dbname=test", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

try {
    $pdo->beginTransaction(); // 相当于 SET AUTOCOMMIT=0 + START TRANSACTION
    
    $pdo->exec("UPDATE accounts SET balance = balance - 100 WHERE user_id = 1");
    $pdo->exec("UPDATE accounts SET balance = balance + 100 WHERE user_id = 2");
    
    $pdo->commit(); // 提交
} catch (Exception $e) {
    $pdo->rollback(); // 回滚
    throw $e;
}
?>

最佳实践 :应用程序中始终使用 beginTransaction() + commit()/rollback()


七、事务使用注意事项

  1. 避免长事务

    长时间未提交的事务会:

    • 占用大量 undo 日志;
    • 阻塞 purge 线程;
    • 增加死锁概率。
  2. 合理选择隔离级别

    • 大多数场景 REPEATABLE READ(默认)足够;
    • Oracle/SQL Server 默认是 READ COMMITTED,注意兼容性。
  3. 死锁处理

    InnoDB 会自动检测死锁并回滚代价较小的事务。应用层应捕获 Deadlock found 错误并重试。

  4. 不要在事务中处理用户交互

    事务期间等待用户输入会导致锁长时间持有,影响并发性能。


八、总结:事务使用口诀

"InnoDB 才支持,ACID 要记牢;
BEGIN 开事务,COMMIT 才生效;
出错就 ROLLBACK,保存点更灵活;
默认可重复读,长事务要避免!"

掌握 MySQL 事务,不仅是写出正确代码的基础,更是构建高可靠、高并发系统的必备技能。合理运用事务,让你的数据在任何情况下都坚如磐石!

相关推荐
Database_Cool_6 小时前
OLTP 和 OLAP 区别详解:分析型数据库和事务型数据库怎么选(附阿里云 AnalyticDB MySQL 选型指南)
数据库·mysql·阿里云
Database_Cool_7 小时前
单机 MySQL 迁移到分布式数据库方便吗?阿里云 PolarDB-X 100% MySQL 协议兼容零改造平滑迁移
数据库·分布式·mysql
姜太小白7 小时前
【MySQL】 索引优化实战:解决 WHERE 等值 + IS NULL 查询,TEXT 字段报错 1167 的完整指南
数据库·mysql
liuxiaowei39 小时前
【绝版教程】新版MySQL DBA高级实战进阶班 MySQL8.0 姜承尧-腾讯数据库总监
数据库·mysql·dba
破碎的南瓜9 小时前
sqli--sql注入过关笔记(1,2,3,4,5,9)
数据库·笔记·sql
Csvn10 小时前
📊 SQL 入门 Day 10:递归 CTE — 破解无限层级查询的终极武器
后端·sql
sg_knight11 小时前
MySQL 存储过程详解:从入门到实战
android·数据库·mysql·database·dba·关系型数据库·db
Database_Cool_13 小时前
企业级多模态分析计算引擎选型:首选 AnalyticDB MySQL 向量 + SQL + 实时一体化方案
数据库·sql·mysql
宇宙第一小趴菜14 小时前
五、Oracle vs MySQL 架构深度对比笔记
mysql·oracle·架构
洵有兮15 小时前
sql注入通关笔记
数据库·笔记·sql·sql注入