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

相关推荐
明天,今天,此时2 小时前
表格形式的数据库表的元数据与SQL字符串互转
数据库·sql·mysql转hivesql·表格形式转sql形式
coNh OOSI2 小时前
如何在 Windows 上安装 MySQL(保姆级教程2024版)
数据库·windows·mysql
SeSs IZED2 小时前
MySQL中查看表结构
数据库·mysql·oracle
Irene19912 小时前
Oracle 21c XE 大数据开发常用 SQL 语法总结(不同 Oracle 版本,sql 语法大部分通用)
大数据·sql·oracle
ZGi.ai2 小时前
自然语言查数据库:Text-to-SQL工程实现与企业落地细节
数据库·sql·nl2sql·text-to-sql
Irene19912 小时前
SQL 中单引号与双引号的使用要求(严格区分)
sql
极客on之路11 小时前
mysql explain type 各个字段解释
数据库·mysql
代码雕刻家11 小时前
MySQL与SQL Server的基本指令
数据库·mysql·sqlserver
lThE ANDE11 小时前
开启mysql的binlog日志
数据库·mysql