1、原子性:食物中的逻辑要全部执行,不可分割(原子是物理中最小单位)
2、一致性:指事务执行前后,数据的完整性保持一致
3、隔离性:指一个事务在执行的过程中不应该受其他事务的影响
4、持久性:事务执行结束(提交或回滚),数据都应持久到数据中
>不考虑隔离级别设置,那么会出现以下问题:
>脏读:指一个事务读到了另一个事务还未提交的数据
>不可重复读:一个事务读到了另一个事务提交的数据,导致多次查询结果不一致
>幻读:一个事务读到了另一个事务已提交的插入的数据,导致多次查询结果不一致
1、读未提交Read Uncommited
>指一个事务可以读取到另一个事务还未提交的数据。这就会引发“脏读”,读取到的是数据库内存中的数据,而非真正磁盘上的数据
演示:
1)开启一个命令行窗口A, 开始事务,然后查询表中记录。 设置当前窗口的事务隔离级别为 读未提交 命令如下:
set session transaction isolation level read uncommitted;
2)另外在打开一个窗口B, 也开启事务, 然后执行 sql 语句, 但是不提交
3)在A窗口重新执行查询, 会看到B窗口没有提交的数据。
2、读已提交Read Commited
>与前面的读未提交刚好相反,这个隔离级别是,只能读取到其他事务已经提交的数据,那些没有提交的数据是读不出来的。但是这会造成一个问题是:前后读取的结果不一样。发生了不可重复!!!所谓的不可重复读,就是不能执行多次读取,分则出现结果不一。
演示:
1)开启一个命令行窗口A, 开始事务,然后查询表中记录。 设置当前窗口的事务隔离级别为 读未提交 命令如下:
set session transaction isolation level read committed;
2)另外在打开一个窗口B, 也开启事务, 然后执行 sql 语句, 但是不提交。
3)在A窗口重新执行查询, 是不会看到B窗口刚才执行sql 语句的结果,因为它还没有提交。
4)在B窗口执行提交。
5)在A窗口中执行查看, 这时候才会看到B窗口已经修改的结果。
6)但是这会造成一个问题是: 在A窗口中, 第一次查看数据和第二次查看数据,结果不一样。
3、可重复读Repeatable Read - MySql 默认的隔离级别就是这个。
>该隔离级别,可以让事务在自己的会话中重复读取数据,并且不会出现结果不一样的状况,即使其他事务已经提交,也依然还是可以显示以前的数据。
演示:
1)开启一个命令行窗口A, 开始事务,然后查询表中记录。 设置当前窗口的事务隔离级别为 读未提交 命令如下:
set session transaction isolation level read committed;
2)另外在打开一个窗口B, 也开启事务, 然后执行 sql 语句, 但是不提交
3) 在A窗口重新执行查询, 是不会看到B窗口刚才执行sql 语句的结果,因为它还没有提交。
4)在B窗口执行提交。
5)在A窗口中执行查看, 这时候查询结果,和以前的查询结果一致。不会发生改变。
4、可串行化Serializable
>该事务级别是最高级别的事务级别。比前面几种都强大一点,也就是前面几种的问题【脏读、不可重复读、幻读】都能够解决。但是有一些缺点。
演示:
1) 开启一个命令行窗口A, 开始事务,然后查询表中记录。 设置当前窗口的事务隔离级别为 读未提交 命令如下:
set session transaction isolation level read serializable;
2)另外在打开一个窗口B, 也开启事务, 然后执行 sql 语句, 但是不提交
3)在A窗口重新执行查询, 会卡主,没有任何信息显示。
4)在B窗口执行提交。
5)在A窗口中执行查看, 这时候才会显示结果。
Serializable 可以防止上面的所有问题,但是都使用该隔离级别也会有问题,比如造成并发的性能问题。其他的事务必须得等当前正在操作表的事务先提交,才能接着往下,否则只能一直等待。
* 按效率划分,从高到低
> 读未提交 > 读已提交 > 可重复读 > 可串行化
* 按拦截程度 ,从高到底
> 可串行化 > 可重复读 > 读已提交 > 读未提交
读未提交
> 引发问题: 脏读
读已提交
> 解决: 脏读 , 引发: 不可重复读
可重复读
> 解决: 脏读 、 不可重复读 , 未解决: 幻读
可串行化
> 解决: 脏读、 不可重复读 、 幻读。
mySql 默认的隔离级别是 可重复读
Oracle 默认的隔离级别是 读已提交