SQL Server事务的四种隔离级别
前言
事务是并发控制的基本单位,也是恢复的基本单位。在SQL中支持事务的概念。所谓事务,是用户定义的一个操作序列(集合),这些操作要么都做,要么一个都不做,是一个不可分割的整体。事务又分为四种隔离级别,隔离级别越低执行效率越高,对系统的开销越低,可以支持更高的并发
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
未提交读 | 是 | 是 | 是 |
读已提交 | 否 | 是 | 是 |
可重复读 | 否 | 否 | 是 |
可序列化 | 否 | 否 | 否 |
CREATE TABLE TESTPRICE
(
XH INT,
PRICE DECIMAL(18,2)
)
读未提交(read UNCOMMITED)
事务中的修改变更,即使事务没有结束(COMMIT或者ROLLBACK),对于其他事务来说,是可以获取到此事务中未提交的数据的。可以读取到未提交的数据,这就是所谓的脏读(Dirty Read),这个级别的事务会导致数据混乱,故在实际情况下一般不用。
begin tran
INSERT INTO TESTPRICE VALUES(1,0.01)
INSERT INTO TESTPRICE VALUES(1,0.02)
waitfor delay '00:00:06:00'
ROLLBACK tran
set tran isolation level READ UNCOMMITTED
SELECT * FROM TESTPRICE
读已提交(read COMMITED)
大多数数据库系统默认的隔离级别就是读已提交(MySQL除外REPEATABLE-READ),简单说就是只能读到已提交事务的数据。但是在此事务中所做的任何修改其他事务是不可见的,这就会导致一个问题就是,一个事务中相同的语句会得到不同的结果。
set tran isolation level READ COMMITTED
begin tran
SELECT * FROM TESTPRICE
waitfor delay '00:00:06:00'
SELECT * FROM TESTPRICE
COMMIT tran
update testprice set price=4.01
可重复读(REPEATABLE Read)
可重复读解决了脏读的问题,也保证了一个事务中多次读取同一块数据是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读(Phantom read)问题。所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务中又在该范围插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom row)。可重复读是MySQL的默认事务隔离级别。
set tran isolation level repeatable read
begin tran
SELECT * FROM TESTPRICE
waitfor delay '00:00:06:00'
SELECT * FROM TESTPRICE
COMMIT tran
begin tran
insert into testprice values(3,10)
COMMIT tran
可串行化(Serializable)
可串行化是最高的隔离级别。它通过强制事务串行执行,避免了前面所说的幻读问题。简单来说,可串行化会在读取的每一行数据上都加上锁,所以可能导致大量的超时和锁争用问题。实际应用中也很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑用该级别