这张表定义了五个隔离级别。 sql
在sql server2005和以后的版本里,默认的隔离级别有两个不一样的执行方式。为了了解这每一种级别, 咱们能够看一些例子。先建一个数据库和一张表吧。 数据库
-- Create a database and table for testing the isolation levels USE master GO IF EXISTS ( SELECT1 FROM sys.databases WHERE name = 'IsolationDB' ) DROP DATABASE IsolationDB ; GO CREATE DATABASE IsolationDB ; GO USE IsolationDB ; GO CREATE TABLE IsolationTest ( col1 INT PRIMARY KEY , col2 VARCHAR(20) ) ; GO INSERT INTO IsolationTest VALUES (10, 'The first row' ) ; INSERT INTO IsolationTest VALUES (20, 'The second row' ) ; INSERT INTO IsolationTest VALUES (30, 'The third row' ) ; INSERT INTO IsolationTest VALUES (40, 'The fourth row' ) ; INSERT INTO IsolationTest VALUES (50, 'The fifth row' ) ; GO先是第一种隔离级别READ UNCOMMITTED
READ UNCOMMITTED容许一个事务读取当前的任何数据,至因而否有提交了写数据的其它事务,它都忽略。例如,虽然另外一个使用者可能有一个事务正在执行数据修改,事务正在独占这个数据,可是一个定义成READ UNCOMMITTED级别的事务能不管如何都能读取数据,而且能进一步对这些读取的数据进行操做。 spa
有隐患,若是那些用户执行了修改的事务以后又要回滚事务,那样修改的又回到老样子。若是咱们基于这个历来都不存在的数据来进行一些数据分析,将会使决定和行动失去意义。 code
看一个例子 server
-- Step 1: -- Start a transaction but don't commit it USE IsolationDB ; GO BEGIN TRAN UPDATE IsolationTest SET col2 = 'New Value' ; --<EXECUTE>在一个查询里,开始了一个事务但没有提交结束。
-- Step 2: -- Start a new connection and change your isolation level USE IsolationDB ; GO SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ; SELECT * FROM IsolationTest ; --<EXECUTE>在另外一个查询里执行设置隔离级别,执行读取操做。
-- Step 3: -- Return to the connection from Step 1 and issue a ROLLBACK ROLLBACK TRANSACTION ; --<EXECUTE>回到第一个查询,执行回滚。
-- Step 4: -- Rerun the SELECT statement in the connection from Step 2 SELECT * FROM IsolationTest ; -- <EXECUT再次执行读取。
在执行第二步时返回的结果是全部的col2 值都是‘new value’,即便事务在第一个查询窗口尚未提交完成。事实上,这个事务可能历来都没有提交。若是咱们基于这个全部数据都同样,而采起一些分析,咱们会懊悔的,由于这些数据有可能还会改变,不是恒久不变的。 事务
第三步,咱们回滚数据,第四步,执行读取,看到col2数据又会到了原来的样子。 数据分析
reading dirty的隐患远非产生一个问题那么简单。若是一条语句在这个READ UNCOMMITTED隔离级别下读取一个表格,或者读取必定范围的数据,会有问题,事务能够更新一行数据,一行移到新的位置。若是读取开始的时间在更新前,那么读取的是原来的行,而实际上行已经移到新位置,这样致使语句又要读一遍了,有可能会读好多遍。 it
另一种状况就是,一行数据尚未读,就可能被更新了,移到新的表格。这样将不能读取完整的行了,会丢失数据。 io