READUNCOMMITTED(未提交读,读脏数据):
读操作不申请锁,所以读操作不会影响写操作请求排他锁.并且允许读取未提交的修改。
READCOMMITTED(已提交读):
是SQL SERVER默认的隔离级别,可以避免读取未提交的数据,隔离级别比READUNCOMMITTED级别高;
读操作要申请并获得共享锁,允许其他读操作读取该锁定的数据,但是写操作必须等待锁释放,一般读操作读取完就会立刻释放共享锁。
注意:但是由于READ COMMITTED读操作一完成就立即释放共享锁,读操作不会在一个事务过程中保持共享锁,也就是说在一个事务的的两个查询过程之间有另一个会话对数据资源进行了更改,会导致一个事务的两次查询得到的结果不一致,这种现象称之为不可重复读.
REPEATABLEREAD(可重复读):
保证在一个事务中的两个读操作之间,其他的事务不能修改当前事务读取的数据,该级别事务获取数据前必须先获得共享锁同时获得的共享锁不立即释放一直保持共享锁至事务完成,所以此隔离级别查询完并提交事务很重要。
例1
窗口1执行如下,没有提交事务。窗口2 查询相同的数据,发现一直处于执行状态。
猜想应该窗口1事务没有提交,不能对数据进行访问
验证:
运行SQL查询正在执行的语句,发现这条语句的状态是挂起的,等待类型LCK_M_S,在等待共享锁。
查看锁的请求
发现在这张表的这条数据上有两个锁,第一个是排他锁,已经授权 ,第二个是共享锁,是等待状态。因为只有等待排他锁释放后才能再加共享锁。所以数据一直在等待共享锁,一直在执行状态
提交窗口1中的事务,排他锁释放,窗口2获取共享锁,查询执行成功。
例2:
在窗口1执行以下语句,不提交事务(窗口1设置的事务隔离对结果没有影响)
在窗口2执行同样的查询语句,将事物隔离设置为READ UNCOMMITTED
可读取窗口1未提交的修改数据。因为当事务为READ UNCOMMITTED,读操作不会申请共享锁
在窗口2执行同样的查询语句,将事物隔离设置为READ COMMITTED/ REPEATABLE READ
不能查询出数据,一直处于等待 ,正在等待共享锁
在窗口2执行同样的查询语句,将事物隔离设置为READ COMMITTED/ REPEATABLE READ
,但在查询表后面添加(NOLOCK),也可查询出窗口1未提交的数据,相当于此条Sql语句的隔离级别设置成了READ UNCOMMITTED
例3:
窗口1 设置为REPEATABLE READ ,执行查询语句如下,未提交事物,窗口2执行更新操作处于等待状态
原因是:窗口1的共享锁没有释放 ,窗口1 提交事物后,窗口2可以运行成功
例4:
窗口1设置为REPEATABLE READ ,查询加上NOLOCK ,执行查询语句如下,未提交事物,窗口2成功执行更新操作
原因是:加了NOlOCK ,改条语句的隔离级别变成了READ UNCOMMITTED ,共享锁在查询结束后会马上释放,而不会等待事物结束。
例5:
窗口1设置隔离级别READ COMMITTED ,未提交事物 ,窗口2 更新成功 。
原因是:共享锁查询后立即就释放了