在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些是在事务内和事务间可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统的开销也更低。
1、未提交读(Read uncommitted)
在未提交读级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为脏读(Dirty Read)。这个级别会导致很多问题,从性能上来说,未提交读不会比其他的级别好太多,但是缺乏其他级别的很多好处,在实际应用中一般很少使用
2、提交读(Read committed)
大多数数据库系统的默认隔离级别都是提交读(但Mysql不是)。提交读满足前面提到的隔离性的简单定义:一个事务开始时,只能“看见”已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别有时候也叫做不可重复读(nonrepeatable read),因为两次执行同样的查询,可能会得到不一样的结果。
3、可重复读(Repeatable read)
可重复读解决了脏读的问题。该级别保证了在同一个事务中多次读取同样记录的结果是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读(Phantom read)问题。所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务中又在该范围插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom row)。可重复读是MySQL的默认事务隔离级别。
4、可串行化(Serializable)
可串行化是最高的隔离级别。它通过强制事务串行执行,避免了前面所说的幻读问题。简单来说,可串行化会在读取的每一行数据上都加上锁,所以可能导致大量的超时和锁争用问题。实际应用中也很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑用该级别。
1.sql server 下一共有6个事务隔离级别
-- Syntax for SQL Server and Azure SQL Database
SET TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED //读未提交
| READ COMMITTED //读提交
| REPEATABLE READ //重复读
| SNAPSHOT //快照
| SERIALIZABLE //可序列化
| READ COMMITTED SNAPSHOT //读提交的快照
}
获取事务隔离级别(isolation level)
DBCC USEROPTIONS
可以看到数据库默认的transaction 级别为 read committed
设置隔离
设置回话隔离
SET TRANSACTION ISOLATION LEVEL <ISOLATION NAME>
--注意:在设置回话隔离时(REPEATABLE READ)两个单词需要用空格间隔开,但是在表隔离中可以粘在一起(REPEATABLEREAD)
设置查询表隔离
SELECT ....FROM <TABLE> WITH (<ISOLATION NAME>)
2.1 read uncommitted 为最低隔离的等级.可以得到没有提交的数据 请看如下的例子
窗口1:
窗口2:
两个脚本窗口一先执行,窗口2后执行,我们可以看到窗口2 出现了脏读,读到了还没有提交的数据 "11".
2.2 read committed
下面引用csdn上的描述
指定语句不能读取已由其他事务修改但尚未提交的数据。 这样可以避免脏读。 其他事务可以在当前事务的各个语句之间更改数据,从而产生不可重复读取和虚拟数据。 该选项是 SQL Server 的默认设置。
实际例子如下:
窗口1:
窗口2:
我们可以看到窗口1的同一个事务中读取同一条数据前后会不一样,导致了 不可重复读取和虚拟数据
3. repeatable read(重复读)
指定语句不能读取已由其他事务修改但尚未提交的行,并且指定,其他任何事务都不能在当前事务完成之前修改由当前事务读取的数据。
只需将 read committed 例子的 isolation level 改为 repeatable read 在执行就可以看出差别.修改等级后,更新操作必须等到第一个事务提交后才可执行
4.serializeable(可串行的)
- 语句不能读取已由其他事务修改但尚未提交的数据。
- 任何其他事务都不能在当前事务完成之前修改由当前事务读取的数据。
- 在当前事务完成之前,其他事务不能使用当前事务中任何语句读取的键值插入新行。
隔离级别 | 脏读 | 不可重复读 | 虚拟读取 |
未提交的读取 | 是 | 是 | 是 |
已提交的读取 | 否 | 是 | 是 |
可重复的读取 | 否 | 否 | 是 |
快照 | 否 | 否 | 否 |
可序列化 | 否 | 否 | 否 |
Hold on, everything is possible.
1.sql server 下一共有6个事务隔离级别
-- Syntax for SQL Server and Azure SQL Database
SET TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED //读未提交
| READ COMMITTED //读提交
| REPEATABLE READ //重复读
| SNAPSHOT //快照
| SERIALIZABLE //可序列化
| READ COMMITTED SNAPSHOT //读提交的快照
}
获取事务隔离级别(isolation level)
DBCC USEROPTIONS
可以看到数据库默认的transaction 级别为 read committed
设置隔离
设置回话隔离
SET TRANSACTION ISOLATION LEVEL <ISOLATION NAME>
--注意:在设置回话隔离时(REPEATABLE READ)两个单词需要用空格间隔开,但是在表隔离中可以粘在一起(REPEATABLEREAD)
设置查询表隔离
SELECT ....FROM <TABLE> WITH (<ISOLATION NAME>)
2.1 read uncommitted 为最低隔离的等级.可以得到没有提交的数据 请看如下的例子
窗口1:
窗口2:
两个脚本窗口一先执行,窗口2后执行,我们可以看到窗口2 出现了脏读,读到了还没有提交的数据 "11".
2.2 read committed
下面引用csdn上的描述
指定语句不能读取已由其他事务修改但尚未提交的数据。 这样可以避免脏读。 其他事务可以在当前事务的各个语句之间更改数据,从而产生不可重复读取和虚拟数据。 该选项是 SQL Server 的默认设置。
实际例子如下:
窗口1:
窗口2:
我们可以看到窗口1的同一个事务中读取同一条数据前后会不一样,导致了 不可重复读取和虚拟数据
3. repeatable read(重复读)
指定语句不能读取已由其他事务修改但尚未提交的行,并且指定,其他任何事务都不能在当前事务完成之前修改由当前事务读取的数据。
只需将 read committed 例子的 isolation level 改为 repeatable read 在执行就可以看出差别.修改等级后,更新操作必须等到第一个事务提交后才可执行
4.serializeable(可串行的)
- 语句不能读取已由其他事务修改但尚未提交的数据。
- 任何其他事务都不能在当前事务完成之前修改由当前事务读取的数据。
- 在当前事务完成之前,其他事务不能使用当前事务中任何语句读取的键值插入新行。
隔离级别 | 脏读 | 不可重复读 | 虚拟读取 |
未提交的读取 | 是 | 是 | 是 |
已提交的读取 | 否 | 是 | 是 |
可重复的读取 | 否 | 否 | 是 |
快照 | 否 | 否 | 否 |
可序列化 | 否 | 否 | 否 |