数据库中事务和隔离级别
1. 事务的应用场景
事务(Transaction)是数据库操作的最小工作单元,保证一组操作要么全部成功,要么全部失败。常见应用场景有:
- 银行转账:A账户扣款、B账户加款,必须同时成功或失败。
- 订单处理:下单时扣减库存、生成订单、写入日志,三者需一致。
- 批量数据处理:如批量插入、更新、删除,需保证原子性。
实战示例:银行转账
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
COMMIT;
-- 如遇异常可用 ROLLBACK;
2. 什么是存储引擎、与事务的关联
存储引擎简介
存储引擎是MySQL用于管理表数据的底层模块。常见的有:
- InnoDB:支持事务、行级锁、外键,适合高并发场景。
- MyISAM:不支持事务,读写性能高,适合读多写少场景。
MyISAM的历史说明
MyISAM在MySQL 5.5(2010年发布)后已被InnoDB取代为默认存储引擎。虽然MyISAM仍可用,但新项目建议优先使用InnoDB,因为其支持事务和更高的数据安全性。
查看表的存储引擎:
SHOW TABLE STATUS LIKE 'table_name';
存储引擎与事务的关系
只有支持事务的存储引擎(如InnoDB)才能使用事务特性。MyISAM等不支持事务,所有操作立即生效,无法回滚。
3. 事务的开启方式
两种开启事务的方式
MySQL支持两种方式手动开启事务:
START TRANSACTION;
-- 执行多条SQL
COMMIT; -- 提交
ROLLBACK; -- 回滚
或
BEGIN;
-- 执行多条SQL
COMMIT;
ROLLBACK;
说明:START TRANSACTION
和BEGIN
效果一致,推荐使用START TRANSACTION
,因为BEGIN
也可作为语句块的起始关键字,容易混淆。
事务的自动提交模式(autocommit)
MySQL默认开启自动提交模式(autocommit=1),即每执行一条SQL语句都会自动作为一个独立事务提交。如果需要多条语句作为一个事务执行,需关闭自动提交或手动开启事务。
查看当前自动提交状态:
SELECT @@autocommit;
关闭自动提交:
SET autocommit = 0;
-- 执行多条SQL
COMMIT; -- 或 ROLLBACK
-- 事务结束后可重新开启自动提交
SET autocommit = 1;
实战场景:
- 自动提交适合简单的单条操作,如单条插入、更新。
- 复杂业务(如转账、批量操作)需关闭自动提交,保证多条语句的原子性。
全局事务的开启(分布式场景)
全局事务通常用于分布式系统(如XA事务),MySQL支持XA语法:
XA START 'xid';
-- 执行操作
XA END 'xid';
XA PREPARE 'xid';
XA COMMIT 'xid'; -- 或 XA ROLLBACK 'xid';
使用场景:跨多个数据库或服务的分布式一致性需求。
4. 事务的隔离级别
隔离级别表格(含中文解释)
隔离级别 | 脏读 | 不可重复读 | 幻读 | 默认引擎支持 | 中文解释(括号内) |
---|---|---|---|---|---|
READ UNCOMMITTED(读未提交) | √ | √ | √ | InnoDB | 允许读取未提交数据,最低隔离级别 |
READ COMMITTED(读已提交) | × | √ | √ | InnoDB | 只能读取已提交数据,Oracle默认 |
REPEATABLE READ(可重复读) | × | × | √ | InnoDB(默认) | 同一事务多次读取结果一致,MySQL默认 |
SERIALIZABLE(可串行化) | × | × | × | InnoDB | 强制事务串行执行,最高隔离级别 |
- √:可能发生
- ×:不会发生
设置隔离级别
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL REPEATABLE READ;
例子说明
脏读(READ UNCOMMITTED)
A事务未提交,B事务能读到A的未提交数据。
-- 事务A
START TRANSACTION;
UPDATE accounts SET balance = 1000 WHERE user_id = 1;
-- 事务B
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT balance FROM accounts WHERE user_id = 1; -- 读到未提交的1000
不可重复读(READ COMMITTED)
同一事务中两次读取同一数据,结果不同。
-- 事务A
START TRANSACTION;
SELECT balance FROM accounts WHERE user_id = 1; -- 第一次读
-- 事务B
START TRANSACTION;
UPDATE accounts SET balance = 900 WHERE user_id = 1;
COMMIT;
-- 事务A
SELECT balance FROM accounts WHERE user_id = 1; -- 第二次读,值变了
幻读(REPEATABLE READ)
同一事务中两次查询范围数据,第二次多了或少了行。
-- 事务A
START TRANSACTION;
SELECT * FROM orders WHERE amount > 1000; -- 查询结果N条
-- 事务B
INSERT INTO orders (amount) VALUES (2000);
COMMIT;
-- 事务A
SELECT * FROM orders WHERE amount > 1000; -- 查询结果N+1条(幻读)
5. 事务相关术语解释
- 脏读(Dirty Read):一个事务读取到另一个未提交事务的数据。
- 不可重复读(Non-repeatable Read):同一事务中多次读取同一数据,结果不同。
- 幻读(Phantom Read):同一事务中两次查询范围数据,第二次多了或少了行。
- 原子性(Atomicity):事务中的操作要么全部成功,要么全部失败。
- 一致性(Consistency):事务执行前后,数据保持一致。
- 隔离性(Isolation):并发事务之间互不影响。
- 持久性(Durability):事务一旦提交,数据永久保存。
如需进一步了解事务的高级用法或分布式事务实践,可参考官方文档或实际业务场景进行测试。
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据