提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
简介
事务是一个操作的集合,他是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功要么同时失败。
例:张三要向李四转账1000:
默认MySQL的事务是自动提交的,即当执行一条DML语句,MySQL会立即隐式的提交事务。
一、事务操作
模拟转账操作:
-- 1. 查询张三账户余额
select * from account where name = '张三';
-- 2. 将张三账户余额-1000
update account set money = money - 1000 where name = '张三';
-- 此语句出错后张三钱减少但是李四钱没有增加
模拟sql语句错误...
-- 3. 将李四账户余额+1000
update account set money = money + 1000 where name = '李四';
方法一:修改事务提交方式:
- 查看当前事务提交方式:1表示自动提交,0表示手动提交。
SELECT @@AUTOCOMMIT;
- 设置事务提交方式:1为自动提交,0为手动提交,该设置只对当前会话有效:
SET @@AUTOCOMMIT = 0;
- 提交事务:
COMMIT;
- 回滚事务:
ROLLBACK;
则上面代码可改为:
select * from account where name = '张三';
update account set money = money - 1000 where name = '张三';
update account set money = money + 1000 where name = '李四';
commit;
--若执行失败:
--ROLLBACK;
方法二:开启事务—>提交事务:
- 开启事务:
START TRANSACTION; 或 BEGIN TRANSACTION;
- 提交事务:
COMMIT;
- 回滚事务:
ROLLBACK;
则上面代码可改为:
START TRANSACTION;
SELECT * FROM account WHERE name = '张三';
UPDATE account set money = money-1000 where name ='张三';
UPDATE account set money = money+1000 where name ='李四';
COMMIT;
--若执行失败:
--ROLLBACK;
二、事务四大特性:ACID
- 原子性(Atomicity):事务是不可分割的最小操作单元,要吗全部成功,要吗全部失败;
- 一致性(Consistency):事务完成时,必须使所有的数据保持一致状态;
- 隔离性(Isolation):数据库系统提供的隔离机制,保证事务不受外部并发操作影响的独立环境下运行;
- 持久性(Durability):事务一旦提交或回滚,它对数据库中数据的改变时永久的。
三、并发事务问题
并发事务问题:A事务B事务在同时操作某一数据库/表时引发的问题。
问题 | 描述 |
---|---|
脏读 | 一个事物读到另一个事务还没有提交的数据 |
不可重复读 | 一个事务先后读取同一条记录,但两次读取的数据不同 |
幻读 | 一个事物按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在 |
1.脏读:
脏读是指一个事务在读取了另一个事务尚未提交的数据时发生的现象。假设有两个并发的事务 A 和事务 B,事务 A 在读取数据的同时,事务 B 对该数据做了修改,并且还没有提交。如果事务 A 读取了这个未提交的数据,就发生了脏读。
举例:
假设用户 A 的账户余额为 1000 元,用户 B 的账户余额为 2000 元。事务 A 在读取用户 A 的余额时,用户 B 同时进行了一笔转账操作将自己的余额减少到 1000 元,并提交了事务。此时事务 A 读取到的用户 A 的余额是 1000 元,但实际上用户 A 的余额还是 2000 元。这就是一个脏读现象。
2.不可重复读:
不可重复读是指一个事务在读取了某个数据后,再次读取该数据时,发现数据已经发生了变化。这是因为在该事务读取数据期间,另一个事务对该数据进行了修改并提交,导致两次读取的结果不一致。
举例:
假设事务 A 在读取某个表中的一条记录时,得到了该记录的某个特定值。而在事务 A 进行其他操作的过程中,事务 B 修改了该记录并提交了事务。此时,事务 A 再次读取该记录时,发现该记录的值已经发生了变化,导致不可重复读的现象。
3.幻读:
幻读是指一个事务在读取某个范围内的数据记录时,发现有新的数据记录被插入,导致两次读取的记录数不一致。幻读与不可重复读的区别在于,幻读重点关注的是新增的数据记录,而不是已有的数据记录的更新。
举例:
假设事务 A 在某个表中按某个条件读取了一批数据记录,然后在事务 A 进行其他操作的过程中,事务 B 插入了一些符合条件的新数据记录,并提交了事务。此时事务 A 再次按照同样的条件读取数据时,发现有新增数据记录出现,导致幻读的现象。
四、事务隔离级别:
事务隔离级别定义了事务在并发执行时,对其他事务操作的可见性和影响的限制程度。标准的 SQL 规范定义了四种事务隔离级别:
另外,MySQL的默认事务隔离级别为 可重复读(Repeatable Read)。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(Read Uncommitted) | √ | √ | √ |
读已提交(Read Committed) | × | √ | √ |
可重复读(Repeatable Read) | × | × | √ |
串行化(Serializable) | × | × | × |
- √表示在当前隔离级别下该问题会出现
- Serializable 性能最低;Read uncommitted 性能最高,数据安全性最差
- 查看事务隔离级别:
SELECT @@TRANSACTION_ISOLATION;
- 设置事务隔离级别:(SESSION 是会话级别,表示只针对当前会话有效,GLOBAL 表示对所有会话有效)
SET [ SESSION | GLOBAL ]
TRANSACTION ISOLATION LEVEL
{READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE };
1.读未提交(Read Uncommitted):
该隔离级别允许一个事务读取另一个未提交的事务所做的修改,可以发生脏读、不可重复读和幻读的问题。
2.读已提交(Read Committed):
该隔离级别要求一个事务只能读取已经提交的,但是可能会发生不可重复读和幻读的问题。
3.可重复读(Repeatable Read):
该隔离级别要求一个事务只能读取已经提交的数据,并且在同一事务中多次读取同样的数据,得到的结果是一致的。但是仍然可能会发生幻读的问题。
4.串行化(Serializable) :
该隔离级别限制了同时执行的事务之间互相访问数据的能力,只有一条事务可以对数据进行读写,避免了所有的并发问题。
一般来说,隔离级别越高,保证数据的一致性就越好,但是对系统的性能影响也越大。因此,在选择事务隔离级别时,需要根据具体业务场景和系统负载情况进行考虑和取舍。