MySQL 事务(transaction)详解
1. 什么是事务
事务是数据库管理系统执行的一个逻辑工作单位,由一个或多个数据库操作组成。事务具有两个重要特性:原子性和一致性。原子性指事务中的所有操作要么都成功执行,要么都不执行;一致性指事务执行前后数据库不能违反约束条件。
在 MySQL 中,事务主要用于处理需要保持一致性的操作。例如,银行转账操作需要保证转出账户金额减少、转入账户金额增加,并且这两个操作要么都执行,要么都不执行。
2. 事务的 ACID 特性
事务具有 ACID 特性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。
- 原子性(Atomicity):事务中的操作要么全部成功执行,要么全部失败回滚。
- 一致性(Consistency):事务执行前后数据库必须保持一致状态,不违反约束条件。
- 隔离性(Isolation):事务的执行过程中不应受其他事务的干扰,各事务相互独立。
- 持久性(Durability):事务一旦提交,其结果应该是永久性的,即使系统崩溃也不会丢失。
3. 事务的基本操作
在 MySQL 中,我们可以使用 BEGIN
、COMMIT
、ROLLBACK
三个关键字来控制事务的开启、提交和回滚。
BEGIN
:开启一个新的事务。COMMIT
:提交当前事务,将所做的修改永久保存到数据库。ROLLBACK
:回滚当前事务,取消所做的修改。
BEGIN; -- 开启事务
-- 执行一系列数据库操作
COMMIT; -- 提交事务
-- 或者出现错误时回滚事务
ROLLBACK;
请注意,MySQL 默认的自动提交模式(auto-commit mode)是开启的,即每条 SQL 语句都会自动成为一个事务。如果开启了自动提交模式,可以使用 SET autocommit=0
禁用自动提交。
4. 事务的隔离级别
事务的隔离级别决定了并发执行事务时各个事务之间的可见性和影响。MySQL 支持四种隔离级别,分别是 READ UNCOMMITTED
、READ COMMITTED
、REPEATABLE READ
和 SERIALIZABLE
。
READ UNCOMMITTED
:最低隔离级别,事务中的修改和未提交的数据都可见。READ COMMITTED
:默认隔离级别,事务中的修改和已提交的数据可见。REPEATABLE READ
:保证同一事务中多次读取同一数据结果一致。SERIALIZABLE
:最高隔离级别,事务串行执行,避免了各种并发问题,但性能较低。
可以使用 SET SESSION TRANSACTION ISOLATION LEVEL
语句设置事务的隔离级别。
-- 设置事务隔离级别为 REPEATABLE READ
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
5. 隐式事务和显式事务
在 MySQL 中,事务可以分为隐式事务和显式事务。
隐式事务是指以自动提交(auto-commit)模式执行的事务,每条 SQL 语句都会自动成为一个事务。
-- 默认为隐式事务,每条 SQL 语句都被自动提交
INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...);
显式事务是通过 BEGIN
、COMMIT
和 ROLLBACK
进行控制的事务。
BEGIN; -- 开启事务
-- 执行一系列数据库操作
COMMIT; -- 提交事务
-- 或者出现错误时回滚事务
ROLLBACK;
6. 在事务中的操作
在事务中进行的数据库操作主要有:插入数据、更新数据和删除数据。
6.1. 插入数据
插入数据可以使用 INSERT INTO
语句。在事务中插入数据时,可以使用 COMMIT
提交事务,或者使用 ROLLBACK
回滚事务。
BEGIN; -- 开启事务
INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...); -- 插入数据
COMMIT; -- 提交事务
-- 或者出现错误时回滚事务
ROLLBACK;
6.2. 更新数据
更新数据可以使用 UPDATE
语句。在事务中更新数据时,可以使用 COMMIT
提交事务,或者使用 ROLLBACK
回滚事务。
BEGIN; -- 开启事务
UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition; -- 更新数据
COMMIT; -- 提交事务
-- 或者出现错误时回滚事务
ROLLBACK;
6.3. 删除数据
删除数据可以使用 DELETE FROM
语句。在事务中删除数据时,可以使用 COMMIT
提交事务,或者使用 ROLLBACK
回滚事务。
BEGIN; -- 开启事务
DELETE FROM table_name WHERE condition; -- 删除数据
COMMIT; -- 提交事务
-- 或者出现错误时回滚事务
ROLLBACK;
7. 事务的异常处理
在事务中,可能会出现异常情况,如主键冲突、唯一索引冲突、空指针异常等。为了保证数据的完整性和一致性,需要对异常进行处理。
7.1. 使用异常处理语句
在事务中可以使用 TRY ... CATCH
语句对异常进行捕获和处理。
BEGIN; -- 开启事务
BEGIN TRY
-- 执行一系列数据库操作
INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...);
UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition;
DELETE FROM table_name WHERE condition;
-- ...
END TRY
BEGIN CATCH
-- 处理异常
ROLLBACK; -- 回滚事务
END CATCH;
COMMIT; -- 提交事务
7.2. 使用回滚点
回滚点是指事务执行过程中可以回到的一个特定位置,可以使用 SAVEPOINT
和 ROLLBACK TO
语句来实现回滚点。
BEGIN; -- 开启事务
SAVEPOINT sp1; -- 设置回滚点
-- 执行一系列数据库操作
INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...);
SAVEPOINT sp2;
UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition;
-- 出现异常时回滚到回滚点 sp2
ROLLBACK TO sp2;
DELETE FROM table_name WHERE condition;
-- ...
COMMIT; -- 提交事务
8. 事务的并发问题
在并发环境下,事务之间可能会出现多种问题,如脏读(dirty read)、不可重复读(non-repeatable read)和幻读(phantom read)等。为了解决这些问题,MySQL 提供了不同的事务隔离级别。
8.1. 脏读
脏读是指一个事务读取到了另一个未提交事务中的数据。可以通过设置合适的隔离级别来避免脏读的问题。
8.2. 不可重复读
不可重复读是指在一个事务内,多次读取同一数据,但得到的结果不一致。可以通过设置合适的隔离级别来避免不可重复读的问题。
8.3. 幻读
幻读是指在一个事务内,多次执行同一查询语句,但得到的记录数不一致。可以通过设置合适的隔离级别和锁机制来避免幻读的问题。
总结
MySQL 的事务是一个重要的概念,它能够保证数据库操作的一致性和完整性。事务具有 ACID 特性,可以通过 BEGIN
、COMMIT
和 ROLLBACK
控制事务的开启、提交和回滚。事务的隔离级别决定了并发执行事务时各个事务之间的可见性和影响。事务中可以执行插入、更新和删除等操作,并且可以通过异常处理和回滚点来处理异常情况。在并发环境下,事务可能会出现脏读、不可重复读和幻读等问题,可以通过设置合适的隔离级别和锁机制来解决。