数据库 - MySQL的事务
目录
前言
一、事务的特性
(一)原子性
(二)一致性
(三)隔离性
(四)持久性
二、事务的控制语句
三、事务隔离级别
(一)读未提交
(二)读已提交
(三)可重复读
(四)可序列化
四、使用场景
五、事务操作
(一)开启事务
(二)提交事务
(三)回滚事务
(四)示例
六、自动提交模式
七、隐式提交
八、提交前的保存点
九、注意事项
十、总结
前言
MySQL 中的事务是数据库管理系统中用来确保多个 SQL 操作以原子性的方式执行的机制。事务可以保证一系列操作要么全部成功,要么全部失败,从而保证数据库的一致性和完整性。
一、事务的特性
事务具有四个重要的属性,简称 ACID:
(一)原子性
事务中的所有操作要么全部成功,要么全部回滚到事务开始前的状态。如果事务中任何一个操作失败,整个事务都会回滚。
(二)一致性
事务的执行不会破坏数据库的一致性约束。即事务执行前后,数据库都应该处于一致的状态。
(三)隔离性
每个事务的操作在未提交之前,对其他事务是不可见的。事务相互独立,即使并发执行时,事务的执行结果与按顺序执行的结果应当一致。MySQL 通过不同的隔离级别来控制事务的并发执行行为。
(四)持久性
一旦事务提交,数据库中的数据就会被永久保存,即使系统崩溃,事务提交的结果也不会丢失。
二、事务的控制语句
控制语句主要有以下几种:
-
START TRANSACTION
或BEGIN
:显式开启一个事务。 -
COMMIT
:提交事务,表示事务中的所有操作成功执行。 -
ROLLBACK
:回滚事务,将数据库状态恢复到事务开始之前。 -
SAVEPOINT
:设置一个保存点,以便在回滚时可以部分回滚到某个点。 -
RELEASE SAVEPOINT
:删除保存点。 -
SET TRANSACTION
:设置事务的隔离级别。
三、事务隔离级别
MySQL 支持四种事务隔离级别,每种级别对并发控制的严格程度不同:
(一)读未提交
事务可以读取其他事务未提交的数据,容易导致脏读的问题。
(二)读已提交
事务只能读取其他事务已经提交的数据,避免了脏读问题,但可能出现不可重复读。
(三)可重复读
事务执行期间,即使其他事务修改了数据,当前事务依然只能看到执行时的快照,避免了不可重复读问题。MySQL 的默认隔离级别是可重复读,同时通过间隙锁机制来防止幻读
(四)可序列化
最严格的隔离级别,所有事务串行化执行,完全避免了脏读、不可重复读和幻读,但并发性能较差。
四、使用场景
事务通常用于涉及多表操作、转账系统等需要保证数据一致性的场景,例如:
-
银行转账:从一个账户扣钱,并往另一个账户加钱,这两个操作必须作为一个原子操作执行,任何一个操作失败,整个事务都必须回滚。
-
订单处理:生成订单时,可能涉及多个表的写操作,比如库存减少、账户扣款、订单创建等,这些操作需要作为一个事务处理。
五、事务操作
事务的开启和提交涉及到控制事务的生命周期。通过显式开启事务,并在事务内执行多个操作,可以确保这些操作要么全部执行成功并提交,要么在失败时回滚所有操作。
(一)开启事务
MySQL 中,可以通过 START TRANSACTION
或 BEGIN
语句显式开启一个事务。开启事务后,执行的 SQL 操作会被暂时保留,直到提交或回滚。
START TRANSACTION
:这是标准的 SQL 语法,用于启动一个新的事务。
START TRANSACTION;
BEGIN
:MySQL 提供的简写形式,与 START TRANSACTION
等效,用于开启事务。
BEGIN;
此时,MySQL 开始记录事务中的所有操作,直到你决定提交或回滚事务。
(二)提交事务
提交事务意味着将事务中的所有操作永久保存到数据库中。使用 COMMIT
语句可以提交当前事务。
COMMIT;
当事务被提交后,所有的修改都会生效,并且这些修改会对其他事务可见。同时,提交后事务就结束了,后续的操作会作为一个新的事务来处理。
(三)回滚事务
如果在事务过程中发生了错误,或者你决定不保存这些操作的结果,可以使用 ROLLBACK
语句回滚事务。回滚意味着撤销事务中的所有操作,数据库会恢复到事务开始之前的状态。
ROLLBACK;
回滚操作通常用于防止因事务部分失败而导致数据库处于不一致状态。
(四)示例
以下是一个典型的事务使用流程,演示如何开启事务、执行多条操作,并根据情况提交或回滚事务。
-- 1. 显式开启事务
START TRANSACTION;
-- 2. 执行多个 SQL 操作
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
-- 3. 提交事务(保存所有更改)
COMMIT;
-- 如果某个操作失败,可以回滚整个事务
-- ROLLBACK;
六、自动提交模式
默认情况下,MySQL 处于自动提交模式,这意味着每一条 SQL 语句都会自动被作为一个独立的事务执行,并在执行后立即提交。要显式控制事务,就需要暂时关闭自动提交模式。
关闭自动提交模式
可以通过设置 autocommit
为 0
来关闭自动提交:
SET autocommit = 0;
此时,MySQL 将不会自动提交操作,必须显式通过 COMMIT
或 ROLLBACK
来结束事务。
-- 手动提交事务
COMMIT;
-- 手动回滚事务
ROLLBACK;
恢复自动提交模式
在完成事务处理后,你可以将 autocommit
设置为 1
,恢复默认的自动提交行为:
SET autocommit = 1;
七、隐式提交
某些 SQL 语句会导致事务隐式提交,即不需要显式调用 COMMIT
,事务会自动提交。常见的隐式提交操作包括:
-
DDL 操作(如
CREATE
,DROP
,ALTER
等)会在执行前自动提交事务,且在执行后也会自动提交。
示例:
-- 创建表之前,事务会自动提交
CREATE TABLE new_table (id INT);
八、提交前的保存点
在事务中,可以通过 SAVEPOINT
设置一个保存点,便于部分回滚事务。如果不想回滚整个事务,可以使用保存点回滚到某个特定的点。
示例:
-- 开启事务
START TRANSACTION;
-- 设置保存点
SAVEPOINT sp1;
-- 执行一些操作
INSERT INTO orders (order_id, customer_id, total_amount) VALUES (1002, 1, 300);
-- 回滚到保存点 sp1
ROLLBACK TO sp1;
-- 提交事务
COMMIT;
九、注意事项
事务的注意事项主要有以下几点:
-
提交事务后,所有的更改将会永久保存,无法再通过
ROLLBACK
撤销。 -
自动提交模式默认开启时,每条 SQL 都是独立事务;关闭自动提交后,必须手动调用
COMMIT
或ROLLBACK
来结束事务。 -
在分布式数据库中或多个系统间的事务处理中,还可能涉及到分布式事务,通过二阶段提交(2PC)等机制来保证数据的一致性。
十、总结
-
使用
START TRANSACTION
或BEGIN
来显式开启事务。 -
通过
COMMIT
提交事务,永久保存修改。 -
如果事务中发生了问题,可以通过
ROLLBACK
撤销操作,恢复数据库到事务开始前的状态。 -
在 MySQL 默认的自动提交模式下,所有操作会被自动提交,如果需要手动控制事务,必须关闭自动提交模式。