最近想起自己做一个博客。记录一些当时学习时候的笔记。
设置事务隔离级别
语法:
set transaction isolation level
作用:
隔离级别用于决定如果控制并发用户如何读写数据的操作,同时对性能也有一定的影响作用。
首先要说一下如果不考虑事物的隔离性,会发生的情况:
1
脏读
意思就是事物
T
读取了另外的一个事务
X
暂未提交的数据,如果事务
X
回滚,则事务
T
就发生了错误读取,也就是脏读。
例如:
update
account
setmoney
=
money
+
100
where
name
=
’B’; (
此时
A
通知
B)
update
account
setmoney
=
money
-
100
where
name
=
’A’;
当只执行第一条
SQL
时,
A
通知
B
查看账户,
B
发现确实钱已到账(此时即发生了脏读),而之后无论第二条
SQL
是否执行,只要该事务不提交,则所有操作都将回滚,那么当
B
以后再次查看账户时就会发现钱其实并没有转。
2
不可重复读
意思就是对于数据库中的某一数据,事务
T1
反复读取了几次,在读取过程中事务
T2
立马修改了这个数据并且提交事务给数据库,则事务
T1
的下一次读取该数据就会返回和上次不一样的数据结果,这就是不可重复读。
3
幻读(虚读)
幻读是事务非独立执行时发生的一种现象。例如事务
T1
对一个表中所有的行的某个数据项做了从
“1”
修改为
“2”
的操作,这时事务
T2
又对这个表中插入了一行数据项,而这个数据项的数值还是为
“1”
并且提交给数据库。而操作事务
T1
的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务
T2
中添加的,就好像产生幻觉一样,这就是发生了幻读。
幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。
有下面四种情况:
第一种情况:
Read committed (
读已提交
)
:可避免脏读的发生
这句的作用是:
指定在读取数据时控制共享
锁以避免脏读,但数据可在事务结束前更改,从而产生不可重复读取或幻像数据。该选项是
SQL Server
的默认值。
第二种情况:
Read uncommitted (
读未提交
)
:最低级别,任何情况都无法保证。
这句的作用是:
执行脏读或
0
级隔离锁定,这表示
不发出共享锁,也不接受排它锁
。当设置该选项时,可以对数据执行未提交读或脏读;在事务结束前可以更改数据内的数值,行也可以出现在数据集中或从数据集消失。该选项的作用与在事务内所有语句中的所有表上设置
NOLOCK
相同。这是
四个隔离级别中限制最小的级别
。
第三种情况:
Repeatable read (
可重复读
)
:可避免脏读、不可重复读的发生。
这句的作用是:
锁定查询中使用的所有数据以防止其他用户更新数据
,但是其他用户可以将新的幻像行插入数据集,且幻像行包括在当前事务的后续读取中。因为并发低于默认隔离级别,所以应只在必要时才使用该选项。
第四种情况:
Serializable (
串行化
)
:可避免脏读、不可重复读、幻读的发生
这句的作用是:
在数据集上放置一个范围锁,以防止其他用户在事务完成之前更新数据集或将行插入数据集内。这是
四个隔离级别中限制最大的级别
。因为
并发级别较低,所以应只在必要时才使用该选项
。该选项的作用与在事务内所有
SELECT
语句中的所有表上设置
HOLDLOCK
相同。
设置数据库的隔离级别一定要是在开启事务之前!