mysql如何使用事务_mysql事务控制语法解析

2次阅读

事务必须显式开启,begin或start transaction缺一不可;mysql默认autocommit=1,多条dml需先开启事务才能统一提交或回滚。

mysql如何使用事务_mysql事务控制语法解析

事务必须显式开启,BEGINSTART TRANSACTION 缺一不可

MySQL 默认是自动提交模式(autocommit=1),每条 DML 语句单独成事务,执行完立刻生效。想把多条语句打包进一个事务,必须先显式开启——只写 COMMITROLLBACK 没用,它们不会触发隐式开始。

常见错误:直接写 UPDATE t1 SET x=1; UPDATE t2 SET y=2; COMMIT;,结果两条更新各自提交,无法回滚。

  • BEGINSTART TRANSACTION 完全等价,任选其一即可
  • 不推荐用 BEGIN WORK,虽兼容但冗余
  • 开启后,后续所有 DML(INSERT/UPDATE/delete)都暂存在当前事务中,直到 COMMITROLLBACK

SAVEPOint 不是必需的,但能解决部分回滚需求

标准事务只有全提交或全回滚两种结局。如果中间某步出错,又不想放弃前面已成功的操作,就得靠 SAVEPOINT 设立标记点。

例如:插入主表、插入从表、更新统计表 —— 若第三步失败,只回滚到第二步之后的状态,保留前两步。

  • 定义:SAVEPOINT sp1;,名字可自定义,同一事务内可设多个
  • 回滚到某点:ROLLBACK TO SAVEPOINT sp1;(注意不是 ROLLBACK TO sp1
  • 释放某个保存点:RELEASE SAVEPOINT sp1;,不影响事务本身
  • 事务结束(COMMITROLLBACK)会自动清除所有保存点

隐式提交语句会让事务意外终止

有些 SQL 语句执行时会强制提交当前事务,哪怕你没写 COMMIT,事务也立刻结束。这是最容易踩坑的地方,尤其在存储过程或混合 DDL/DML 场景中。

典型触发隐式提交的语句包括:CREATE tableDROP TABLEALTER TABLETRUNCATE TABLELOCK TABLESFLUSH LOGS 等。

  • 示例:BEGIN; INSERT INTO t VALUES(1); CREATE TABLE tmp(id INT); INSERT INTO t VALUES(2); COMMIT; → 实际只有最后一条 INSERT 受事务保护
  • select 不会隐式提交,但 SELECT ... for UPDATESELECT ... LOCK IN SHARE MODE 属于事务内加锁操作,仍需在事务中使用
  • DDL 类操作尽量放在事务外,或确认是否真需要与 DML 绑定

事务隔离级别影响可见性,SET TRANSACTION ISOLATION LEVEL 必须在 BEGIN 前设置

MySQL 的默认隔离级别是 REPEATABLE READ,但如果你需要读已提交(READ COMMITTED)来避免间隙锁或适配其他数据库行为,得手动改——而且时机很关键。

错误写法:BEGIN; SET TRANSACTION ISOLATION LEVEL READ COMMITTED; → 此时事务已开启,该语句无效,级别仍是启动时的默认值。

  • 正确方式:在 BEGIN 前执行,如 SET TRANSACTION ISOLATION LEVEL READ COMMITTED; BEGIN;
  • 也可用会话级设置:SET session TRANSACTION ISOLATION LEVEL READ COMMITTED;,之后所有新事务都生效
  • READ UNCOMMITTEDSERIALIZABLE 同理,不能在事务中动态切换

事务的边界比看起来更“脆”:一条 DDL、一个连接中断、甚至某些客户端自动重连行为,都可能让 BEGIN 形同虚设。实际写业务逻辑时,别只盯着 COMMIT 写在哪,先确认事务是不是真的从你想的位置开始了。

text=ZqhQzanResources