数据库事务

database_transaction2026-10-17 18:47:37

数据库事务把一组数据库操作组织成具有提交或回滚边界的工作单元,常以 ACID 描述其主要保证。

ACID

原子性要求事务效果全部提交或回滚;一致性要求事务维护约束及应用定义的不变量;隔离性规定并发事务的可见性与相互影响;持久性关注提交结果在故障后的保存保证,实际仍需理解产品和配置。

业务边界

同库内的创建订单与条件扣库存可以放进一个事务,失败时回滚相关修改。事务并不会自动证明库存规则正确,仍需约束、条件更新或恰当加锁。

数据库回滚通常不能撤销已发送邮件、外部支付或其他系统的写入。跨边界操作需要单独设计协调和恢复机制,避免把事务拉长到外部调用结束。

提交与回滚怎样理解

事务可以理解为一批有共同完成边界的修改。例如转账时,付款账户扣款与收款账户加款需要一起成立;只完成一半就会破坏业务规则。

  • START TRANSACTION:显式开始一个事务。
  • COMMIT:确认本事务中的修改。
  • ROLLBACK:撤销本事务尚未提交的修改。

提交和回滚针对当前连接的当前事务。在另一个控制台执行回滚,不能替原连接结束事务。回滚也不能撤销已经提交的数据。

在 MySQL InnoDB 中,默认自动提交开启,成功的普通单条语句通常自行提交;显式开始事务或关闭自动提交后,需要理解实际事务边界。数据库客户端也可能使用手动提交。部分 DDL 会隐式提交,因此不能把所有 SQL 都当作可随意回滚的普通修改。

锁是什么

数据库锁是协调并发访问的机制:当一个事务访问某个受保护的数据范围时,其他不兼容的访问需要等待。它类似多人修改同一份资料时的占用标记,用来防止修改相互冲突。

InnoDB 中,共享锁允许兼容的读取;排他锁用于排斥其他不兼容的读写锁。锁既可能涉及记录,也可能涉及索引间隙等范围,不能简单理解为永远只锁一条业务记录。普通一致性查询通常通过多版本机制读取,不等同于 SELECT ... FOR UPDATE 这样的加锁查询。

事务是操作的完成边界,锁是并发协调手段,二者不是同一概念。并非每个事务都会持有阻塞别人的排他锁,但更新等操作持有的锁可能持续到事务结束。

为什么没有执行 SQL 仍会阻塞别人

一个典型场景是:

  1. 连接 A 开始事务,更新某条记录,但没有提交或回滚。
  2. A 暂时不再发送 SQL,连接显示 Sleep。
  3. 连接 B 更新同一受锁范围,需要等待 A 释放锁。
  4. B 等待超过时限,报告 Lock wait timeout exceeded。
  5. A 提交、回滚或断开并完成事务清理后,B 才可能重新执行成功。

Sleep 描述连接当前没有执行命令,不保证其事务已经结束。INNODB_TRX 中 trx_query = NULL 也不代表没有事务或锁。另一方面,大量连接池空闲连接本来就是正常现象,不能只因为 Sleep 就判断它是阻塞者。

锁等待超时与数据库死锁不同:等待超时不要求存在互相等待的循环。MySQL InnoDB 默认遇到锁等待超时时通常只回滚失败语句,整个事务可能还在;开启 innodb_rollback_on_timeout 后行为不同。处理错误时应检查事务边界,而不是以为报错自动清理了一切。

如何排查 MySQL 锁等待

以下为 MySQL 8.0/8.4 的只读检查示例,需要相应监控权限:

SELECT trx_mysql_thread_id, trx_started, trx_state, trx_query
FROM information_schema.innodb_trx
ORDER BY trx_started;

SHOW FULL PROCESSLIST;

SELECT * FROM performance_schema.data_lock_waits;

前两个查询用于关联事务与连接,不能仅凭“最老事务”或“空闲时间长”认定阻塞关系。第三个查询提供当前锁等待关系,需要结合 performance_schema.data_locks、事务及连接信息定位;失败语句已超时后,等待关系可能已经消失。不同 MySQL 版本的监控表和权限可能不同。

找到持锁事务后,优先由所属业务或原客户端决定提交还是回滚。不要为了释放锁而盲目提交不完整业务。

确需终止连接时,KILL CONNECTION <连接ID> 会断开目标连接,未提交的 InnoDB 事务需要回滚,释放锁可能需要时间;KILL QUERY 只终止当前语句,不等于结束连接或清理整个事务。终止前应确认连接身份和可放弃的未提交工作,不能把截图中的历史连接 ID 当作长期有效的操作目标。

实际预防上,应缩短事务,及时处理异常和结束事务,避免在持锁期间等待人工操作或外部网络。重试还需要考虑操作幂等性和事务整体是否可安全重做。

参考资料

本页目录