>[info]事务,是现实生活中的一组逻辑操作单元,这组操作要么全部成功,要么全部失败
例子:转账
张三-500元
李四+500元
**事务的特性(ACID)**
- 原子性(automicity):事务不可再分割,要么全执行,要么全不执行。实现主要基于undo log(回滚日志文件)
- 一致性(consistency):执行事务会是数据从一个一致状态切换到另一个一致状态
- 隔离性(isolation):事务执行不受其他事务的干扰。实现主要基于锁机制、数据的隐藏列、undo log和类next-key lock机制
- 持久性(durability):事务一旦提交,将永久改变数据库数据。实现主要基于redo log(重做日志文件)
两个并发事务一定会出现“脏读”,即读到的数据不准确
<br/>
## 6.1 脏读、不可重复读和幻读
首先来看并发情况下,读操作可能存在的三类问题:
- (1)脏读:当前事务(A)中可以读到其他事务(B)未提交的数据(脏数据),这种现象是脏读。
举例如下(以账户余额表为例):
```
事务A和B在T1时刻同时开启事务;
事务B在T2时修改“张三”余额由100变为200;
事务A在T3时查询“张三”的余额,结果为200【脏读】(因为事务B还没有提交事务)
事务B在T4时提交事务
```
- (2)不可重复读:在事务A中先后两次读取同一个数据,两次读取的结果不一样,
这种现象称为不可重复读。脏读与不可重复读的区别在于:前者读到的是其他事务未提交的数据,
后者读到的是其他事务已提交的数据。举例如下:
```
事务A和B在T1时刻同时开启事务;
事务A在T2时查询“张三”的余额,结果为100修改“张三”余额由100变为200;
事务B在T3时修改“张三”余额由100变为200;
事务B在T4时提交事务
事务A在T5时查询“张三”的余额,结果为200【不可重复读】(两次读到的数据不一样)
```
- (3)幻读:在事务A中按照某个条件先后两次查询数据库,两次查询结果的条数不同,
这种现象称为幻读。不可重复读与幻读的区别可以通俗的理解为:前者是数据变了,
后者是数据的行数变了。举例如下:
```
事务A和B在T1时刻同时开启事务;
事务A在T2时查询0<id<5的所有用户的余额,结果只查到“张三:100(id=1)”;
事务B在T3时向余额表中插入新用户:李四:200(id=2);
事务B在T4时提交事务;
事务A在T5时再次查询0<id<5的所有用户的余额,结果查到“张三:100(id=1) 李四:200(id=2)“【幻读】(不应该查到李四)
```
<br>
## 6.2 事务的创建
>隐式事务:事务没有明显的开启和结束的标记
比如insert、update、delete语句,会自动开启事务
delete from 表 where id =1;
> 显式事务:事务具有明显的开启和结束的标记
> 前提:必须先设置自动提交功能为禁用
> 在自动提交模式下,如果没有 start transaction 显式地开始一个事务,
> 那么每个 sql 语句都会被当做一个事务执行提交操作。
(1). 开启事务
```
set autocommit=0;
start transaction;(可选)
```
(2).编写事务的sql语句
(3).结束事务
```
commit;
rollback;
```
>[success]mysql 的默认隔离级别为:repeatable read 可重复读
Oracle的默认隔离级别为:read committed 读 已提交
隔离级别(isolation)
| | 脏读 | 不可重复读 | 幻读 | 第一类丢失更新 | 第二类丢失更新
| :-- | :-: | :-: | :-: | :-: | :-: |
| read uncommitted | √ | √ | √ | × | √ |
| read committed | × | √ | √ | × | √ |
| repeatable eead | × | × | √ | × | × |
| serializable | × | × | ×| × | × |
查看隔离级别
`select @@tx_isolation;(以后看到tx,要知道它表示事务的意思)
`
设置隔离级别
```
set session|global transaction isolation level 隔离级别;
session 会话,表示设置的隔离级别只在当前会话中有效;
global 全局,表示设置的隔离级别在所有的会话中都有效(但是其他需要重启一次会话,不然其他的会话加载的内容会是设置全局级别之前的内容)
```
比如:打开浏览器输入百度,就表示 你与浏览器开始了一个会话,关闭窗口就结束本次会话。
再比如,你打开cmd,输入命令,就表示开启了与命令行的会话
<br>
数据库引擎:
**MyISAM引擎**,不支持事务;只支持表锁。
**innoDB引擎**支持事务,也支持表锁和行锁
>行锁:当两个不同事务操作同一个数据(并发执行),前一个事务还没有结束事务(提交或回滚),后一个事务就无法执行操作(会陷入等待状态)
>表锁:与行锁功能相同,但是不限于当前行的数据,而是整个表的其他数据都不能修改(除非当前事务结束)
行锁开销大,粒度小,并发性好;表锁开销小,粒度大,并发性差