事务的简介
事务是一组操作的集合,事务会把所有操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
默认MySQL的事务是自动提交的,也就是说,当执行一条增删改查语句时,MySQL会立即隐式的提交事务,事务也可以我们手动开启事务,回滚事务和提交事务。
每一次sql都是一个事务,运行完成,自动提交事务。
事务的操作
查看/设置事务提交方式,1是默认提交,0是手动提交,
SELECT @@AUTOCOMMIT
SET @@AUTOCOMMIT=0
----------------------------
开启事务
START TRANSACTION 或者 BEGIN;
----------------------------
提交事务
COMMIT;
----------------------------
回滚事务
ROLLBACK;
事务的四的特性
原子性:事务是不可分割的最小单元,要么全部成功,要么全部失败。
一致性: 事务完成时,必须使所有的数据保持一致的状态。
隔离性: 数据库系统提供了隔离机制,保证事务在不受外部并发操作影响的独立环境下运行,多个事务,不会相互影响,他们都是在单独的一个空间进行运行。
持久性: 事务一旦提交或回滚,他对数据中的数据的改变是永久的。事务一旦提交或回滚就会永久保证在磁盘里。
并发事务问题
问题 | 描述 |
---|---|
脏读 | 一个事务读到另一个事务还没提交的数据 |
不可重复读 | 一个事务先后读取同一条记录,但两次读取的数据不同 |
幻读 | 一个事务按照条件查询数据时,没有对应的数据行,但是再插入数据时,又发现这行数据已经存在 |
事务隔离级别
√表示在当前隔离级别下该问题会出现
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable Read(默认) | × | × | √ |
Serializable | × | × | × |
Read uncommitted:
- 读未提交,最低的隔离级别,可能造成脏读、不可重复读、幻读。
- 所以一般情况下,该隔离级别在实际应用中很少使用。
Read committed(oracle默认):
- 读已提交,可以避免脏读,但是可能造成不可重复、幻读。
- 两个事务并发执行,事务a第一次查询是1, 事务b随后将1更新成了2并提交了该事务,事务a第二次查询是2 。
- 事务和事务之间,更新数据表(删除,添加,修改)并提交事务,其他事务读取的都是你提交后的数据,隔离性比较差。
- 一个事务所做修改在最终提交以前,对其他事务是不可见的。换句话说,一旦提交,该事务所作的修改对其他正在进行中的事务就是可见的。
- 这是大多数数据库系统的默认事务隔离级别(例如 Oracle、SQL Server),但不是 MySQL 默认的。
- 使用可重复读隔离级别可以解决实例中产生的不可重复读问题。
Repeatable Read(MySQL默认):
- 可重复读,可以避免脏读和不可重复读,但是可能造成幻读。
- 两个事务并发执行,事务a第一次查询是1, 事务b随后将1更新成了2并提交了该事务,事务a第二次查询是还是1
- 事务和事务之间,更新数据并提交事务,并不影响我读取数据,事务和事务之间是隔离的,但是会出现幻读的情况,如:事务a第一次查询是三条数据,事务b随后又提交一条id为4的数据并提交了该事务,事务a第二次查询是还三条,后续想添加id为4的数据时发现已经有该数据了。
- 可重复读解决了部分不可重复读的问题:同一个事务中多次读取同样记录结果是一致的。记录指具体的数据行。
Serializable:
- 串行化,进行并发事务的时候,只允许一个事务进行操作,操作完成,后面的操作才能继续操作。
- 最高的隔离级别,完全服从ACID的隔离级别,所以的事务依次执行,可以避免脏读、不可重复读、幻读。
- 但是该事务隔离级别执行效率低下,且性能开销也最大,所以一般情况下不推荐使用。
从上往下隔离级别越高。
事务隔离基本越高,数据越安全,但是性能差。
Serializable 性能最低,隔离级别高;
Read uncommitted性能最高,数据安全性最差, 一般情况下不会更改事务隔离级别。
不可重复读侧重于修改,幻读侧重于新增或删除。
MySQL InnoDB存储引擎的可重复读并不能避免幻读,需要应用使用加锁读来保证,这加锁读使用到的机制就是Next-Key Locks。
因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是读取已提交(READCOMMITTED),InnoDB 存储引擎默认使用 REPEATABLE-READ(可重读) 并不会有任何性能损失。
InnoDB存储引擎在分布式事务的情况下一般会用到可串行化隔离级别。
查看事务隔离级别:
SELECT @@TRANSACTION_ISOLATION;
设置事务隔离级别:
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE };
SESSION 是会话级别,表示只针对当前会话有效,GLOBAL 表示对所有会话有效
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
文章参考:哔哩哔哩动画 bilibili.com 博主:黑马程序员。
如果想转发和使用请加上作者和网址,谢谢!
如果发现文章有问题请指出,谢谢!
后续会继续更新,阅读请关注小昵称。