1. 什么是事务
事务是由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行逻辑单元。在同一个事务当中,这些操作最终要么全部执行成功,要么全部失败,不会存在部分成功的情况。
2. 事务的特性
事务的四个最主要的特性ACID,A:原子性,C:一致性,I:隔离性,D:持久性
原子性(Atomicity)
就是指一个事务的操作是一个原子操作,事务中的所有语句要么全部成功要么全部失败,不会存在其中一条成功另一条失败的情况。
一致性(Consistency)
就是指一个事务从一个状态,变到另一个状态,不能破坏数据的完整性。
举个例子就是A给B转账500块钱,然后A的钱减少了,那么B的钱一定要增加,不能A的钱减少了,B的钱没有增加,或者B的钱增加了,A的钱没有减少。
隔离性(Isolation)
是指一个事务的操作不会对另一个事务产生干扰,也就是在并发的情况下,两个事务之间不会产生干扰。
持久性(Durability)
是指一个事务一旦提交,那么他对数据库中数据的改变是永久的,不会出现再次变回原先数据的情况,除非你再次提交事务进行修改。
3. 事务的控制语句
- BEGIN 或 START TRANSACTION 显式地开启一个事务;
- COMMIT 提交事务,使已对数据库进行的所有修改成为永久性的;
- ROLLBACK 回滚会结束用户的事务,撤销正在进行的所有未提交的修改;
- SAVEPOINT identifier,在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;
- RELEASE SAVEPOINT identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
- ROLLBACK TO identifier 把事务回滚到标记点;
- SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。
- SHOW VARIABLES LIKE 'transaction_isolation' 查看事务的隔离级别
4. 事务中出现的问题
由于并发原因,事务根据不同的隔离级别可能会出现脏读,不可重复读,幻读这三种问题。
脏读
是指一个事务读取到了另一个事务没有提交的数据, 比如事务A读取了事务B更新的数据,然后事务B对更新操作进行回滚,那么事务A读取到的数据是脏数据。
不可重复读
是指一个事务多次读取到的结果不一致。比如事务A多次执行一个查询语句,在查询语句之间有个事务B更新了这条语句,并提交,此时会造成事务A在后一次读取到的是事务B更新后的数据,与之前读取到的数据不一致,这就是不可重复读。
幻读
是指多次读取到的数据的数量发生了变化。比如事务A两次查询相同条件的数据数量,然后在两个查询之间事务B插入一条该条件的数据,并提交,此时会导致事务A两次查询相同条件的数据的数量不一致,就像是发生了幻觉一样。这就是幻读。
5. 事务的隔离级别
事务的隔离级别主要分为四种,分别是READ-UNCOMMITTED(读未提交),READ-COMMITTED(读已提交),REPEATABLE-READ(可重复读),SERIALIZABLE(序列化)。
READ-UNCOMMITTED(读未提交)
其隔离级别最低,并且允许脏读取。换句话说就是一个事务更改了一个数据,然后这个事务并没有提交,但是其更改的数据会被另一个事务读取到。如下:
时间点 | 事务A | 事务B |
---|---|---|
T1 | 开始事务 | |
T2 | 开启事务 | |
T3 | 将某个字段的值从3改到4 | |
T4 | 读取该字段的值为4 | |
T5 | 事务回滚 | |
T6 | 事务提交 | |
T7 | 事务提交 |
结论:可以从上面的时间段的表格中可以看到,在事务B将字段的值从3改到4时,此时事务A读取到的该字段的值为4,事务B再进行回滚,数据又变回了3,那么事务A读取到的值就是脏数据了。这就是读未提交会出现脏读取。
READ-COMMITTED(读已提交)
其隔离级别比读未提交高一级别,oracle数据库的隔离级别默认是该级别,其允许读取事务已经提交的结果,该隔离级别不会产生脏读,但是其可能会产生不可重复读。如下:
时间点 | 事务A | 事务B |
---|---|---|
T1 | 开始事务 | |
T2 | 读取到的某个字段的值为3 | |
T3 | 开启事务 | |
T4 | 将该字段的值从3改到4 | |
T5 | 事务提交 | |
T6 | 再次读取该字段的值为4 | |
T7 | 事务提交 |
结论:可以从上面的时间段表格中看出,事务A刚开始读取到的某个字段的值为3,然后有个事务B过来将该字段修改后提交,然后事务A再次读取到的该字段的值为4。可见再事务A的两次读取中,该字段的值不一样,这就是不可重复读。
REPEATABLE-READ(可重复读)
它是比读已提交更高一级的隔离级别,mysql数据库默认的隔离级别就是可重复读,该级别保证了同一个事务中多次读取的同一个字段的值是相同的。如下:
时间点 | 事务A | 事务B |
---|---|---|
T1 | 开始事务 | |
T2 | 读取到的某个字段的值为3 | |
T3 | 读取到该表中的数据为4条 | |
T4 | 开启事务 | |
T5 | 将该字段的值从3改到4 | |
T5 | 向该表中插入一条新的数据 | |
T6 | 事务提交 | |
T7 | 再次读取该字段的值为3 | |
T8 | 再次读取该表中的数据为5条 | |
T9 | 事务提交 |
结论:由上面的时间段表中可以看出,事务A起初读取到的某个字段的值为3,该表中的数据量为4,然后事务B将该字段更改为4同时新插入了一条数据,事务A再次读取的该字段值还是为3,但是读取到的该表的数据量变为了5条,就像发生了幻觉一样,由此可以知道该隔离级别不会发生不可重复读,但是会产生幻读。另外,幻读与不可重复读主要的区别是不可重复读主要是数据的值变化,而幻读主要是数据的量变化。
SERIALIZABLE(序列化)
它是最高的隔离级别,要求所有的事务排队顺序执行,即事务只能一个接一个地处理,不能并发。
6. 事务不同隔离级别下可能会出现的问题
脏读 | 幻读 | 不可重复读 | |
---|---|---|---|
读未提交 | 会 | 会 | 会 |
读已提交 | 不会 | 会 | 会 |
可重复读 | 不会 | 不会 | 会 |
序列化 | 不会 | 不会 | 不会 |
7. 总结
事务的隔离级别并不是越高越好的,这个要根据实际情况来进行选择,事务隔离级别越高的话其并发度就越低。基本上常用的事务隔离级别是读已提交和可重复读这两种。
标签:事务,隔离,数据,提交,Mysql,级别,读取 From: https://www.cnblogs.com/mcj123/p/17038410.html