Mysql事务
Mysql事务
MySQL 事务是数据库管理系统中用于确保数据一致性和完整性的重要机制。事务将一系列操作作为一个整体执行,要么全部成功,要么全部失败。
事务的特性(ACID)
事务具有以下四个特性,通常称为 ACID 特性:
- 原子性(Atomicity):事务中的所有操作要么全部成功,要么全部失败。如果事务中的任何操作失败,整个事务将回滚到初始状态。
- 一致性(Consistency):事务执行前后,数据库的状态必须保持一致。即事务执行后,数据库从一个有效状态转换到另一个有效状态。
- 隔离性(Isolation):多个事务并发执行时,一个事务的操作不应影响其他事务。MySQL 提供了不同的事务隔离级别来控制事务之间的可见性。
- 持久性(Durability):一旦事务提交,其对数据库的修改将永久保存,即使系统崩溃也不会丢失。
事务的基本操作
MySQL 中事务的基本操作包括:
-
BEGIN 或 START TRANSACTION:开始一个新的事务。
-
COMMIT:提交事务,使事务中的所有操作永久生效。
-
ROLLBACK:回滚事务,撤销事务中的所有操作,恢复到事务开始前的状态。
-
SAVEPOINT:在事务中创建一个保存点,允许部分回滚到该保存点。
-
ROLLBACK TO SAVEPOINT:回滚到指定的保存点。
-
RELEASE SAVEPOINT:删除一个保存点。
START TRANSACTION; 或者BEGIN; --开启事务 COMMIT; --提交事务 ROLLBACK; --回滚事务 SAVEPOINT savepoint_name; --设置保存点 ROLLBACK TO savepoint_name; --回滚到保存点 RELEASE SAVEPOINT savepoint_name; --释放保存点
基本操作中的注意事项
-
自动提交
-
MySQL 默认启用自动提交模式,每个语句都会自动提交。可以通过
SET autocommit = 0;禁用 -
自动提交是 MySQL 的一个默认行为,当 autocommit 设置为 1(默认值)时,每条 SQL 语句都会自动被视为一个独立的事务,并在执行成功后立即提交
-
这意味着,如果执行一条 INSERT、UPDATE 或 DELETE 语句,MySQL 会自动将其包装在一个事务中,并在执行成功后立即提交,无需显式地使用 COMMIT
-
当 autocommit = 0 时,需要显式地开始一个事务(使用 START TRANSACTION 或 BEGIN),并在事务结束时使用 COMMIT 提交或 ROLLBACK 回滚
-
如果没有创建保存点,执行ROLLBACK默认退回到事务开始的状态
-
查看当前的
autocommit状态-
SELECT @@autocommit;
-
-
连接级别的设置:autocommit 的设置是基于每个数据库连接的。如果在一个连接中禁用了自动提交,其他连接不会受到影响
-
-
事务控制范围
- 受事务控制的语句主要是 DML(数据操作语言) 语句,这些语句会对数据进行增删改操作,并且可以通过事务管理来保证原子性
- INSERT:插入数据
- UPDATE:更新数据
- DELETE:删除数据
- SELECT ... FOR UPDATE:锁定查询结果集(用于事务中的悲观锁)
- 不受事务控制的语句主要是 DDL(数据定义语言) 和 DCL(数据控制语言) 语句。这些语句在执行时会隐式提交当前事务,无法回滚
- CREATE:创建数据库对象(如表、索引、视图等)
- ALTER:修改数据库对象
- DROP:删除数据库对象
- TRUNCATE:清空表数据
- RENAME:重命名表
- DCL:GRANT:授予用户权限、REVOKE:撤销用户权限
- 其他不受事务控制的语句
- SET:设置系统变量或用户变量
- USE:选择数据库
- LOCK TABLES 和 UNLOCK TABLES:锁定和解锁表
- 执行 DDL 或 DCL 语句时,MySQL 会隐式提交当前事务,例如,如果在一个事务中执行了 INSERT,然后执行了 CREATE TABLE,INSERT 会被自动提交,无法回滚
- MySQL 中只有支持事务的存储引擎(如 InnoDB)才能使用事务管理。不支持事务的存储引擎(如 MyISAM)无法使用事务
- 受事务控制的语句主要是 DML(数据操作语言) 语句,这些语句会对数据进行增删改操作,并且可以通过事务管理来保证原子性
事务的隔离级别
事务的隔离级别是数据库管理系统用来控制事务之间可见性和并发性的重要机制。不同的隔离级别提供了不同程度的数据一致性保证和并发性能。MySQL 支持四种标准的事务隔离级别,分别是:
- READ UNCOMMITTED(读未提交)
- READ COMMITTED(读已提交)
- REPEATABLE READ(可重复读)
- SERIALIZABLE(串行化)
READ UNCOMMITTED(读未提交)
- 最低的隔离级别,允许事务读取其他事务未提交的数据变更
- 脏读(Dirty Read):事务可以读取到其他事务未提交的数据。如果这些未提交的数据被回滚,那么读取到的数据就是无效的
- 对数据一致性要求不高的场景,如某些统计查询
READ COMMITTED(读已提交)
- 事务只能读取其他事务已经提交的数据
- 避免脏读:事务不会读取到未提交的数据,避免了脏读问题
- 不可重复读(Non-Repeatable Read):在同一事务中,多次读取同一数据可能会得到不同的结果,因为其他事务可能在两次读取之间提交了数据变更
REPEATABLE READ(可重复读)
- MySQL 的默认隔离级别,确保在同一事务中多次读取同一数据时结果一致
- 避免脏读和不可重复读:事务在执行期间看到的数据是一致的,即使其他事务提交了数据变更
- MySQL 使用 多版本并发控制(MVCC, Multi-Version Concurrency Control) 来实现 REPEATABLE READ
- 每个事务在开始时会创建一个“快照”(Snapshot),事务中的所有读取操作都基于这个快照,而不是实时读取数据库的最新状态
- 幻读(Phantom Read):在同一事务中,多次执行相同的查询可能会返回不同的行数,因为其他事务可能插入了新的数据
- 尽管 REPEATABLE READ 使用快照来防止部分幻读,但在某些情况下,幻读仍然可能发生
- 写操作(如 UPDATE 或 DELETE)会重新评估数据范围
- 如果事务 A 执行了一个写操作(如 UPDATE accounts SET balance = balance + 10 WHERE balance > 100),MySQL 会重新评估 WHERE 条件
- 在重新评估时,MySQL 会基于当前数据库的最新状态(而不是事务 A 的快照)来确定哪些行满足条件
SERIALIZABLE(串行化)
- 最高的隔离级别,确保事务串行执行,完全隔离
- 为了完全防止幻读,MySQL 在 REPEATABLE READ 隔离级别下使用了 间隙锁(Gap Lock) 和 临键锁(Next-Key Lock)
- 间隙锁:锁定一个范围,防止其他事务在这个范围内插入新数据。
- 临键锁:结合记录锁和间隙锁,锁定一个记录及其前后的范围。
- 为了完全防止幻读,MySQL 在 REPEATABLE READ 隔离级别下使用了 间隙锁(Gap Lock) 和 临键锁(Next-Key Lock)
查看事务隔离级别
-
查看当前会话的事务隔离级别
SELECT @@transaction_isolation; -
查看全局的事务隔离级别
SELECT @@global.transaction_isolation;
设置数据库隔离级别
-
设置当前会话的隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET SESSION TRANSACTION ISOLATION LEVEL <隔离级别>; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; -
设置全局隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL <隔离级别>; SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ; -
也可以在事务开始时设置隔离级别
START TRANSACTION; SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- 事务操作 COMMIT; -
修改全局隔离级别会影响所有新会话,已存在的会话不受影响
-
修改会话隔离级别仅影响当前会话
-
需要 SUPER 权限才能修改全局隔离级别

浙公网安备 33010602011771号