SNAPSHOT隔离级别不会产生死锁,但是可以防止更新冲突。通过储存的版本可以检测更新冲突,如果在一个事务的读取与写入之间另外一个事务修改了数据,那么这个事务将会失败。
  加入连接1首先进行读数据:
  BEGIN TRAN;
  SELECT productid, unitprice FROM Production.Products WHERE productid = 2;
  在连接2中更新数据:
  BEGIN TRAN;
  UPDATE Production.Products SET unitprice += 1.00 WHERE productid = 2;
  COMMIT TRAN;
  那么在连接1中重新更新数据,并提交事务:
  UPDATE Production.Products SET unitprice = 21.00 WHERE productid = 2;
  COMMIT TRAN;
  那么这个事务会提交失败,因为检测到了更新冲突。错误信息如下:
  消息 3960,级别 16,状态 2,第 1 行
  快照隔离事务由于更新冲突而中止。您无法在数据库'AdventureWorks2012'中使用快照隔离来直接或间接访问表 'Production.Products',以便更新、删除或插入已由其他事务修改或删除的行。请重试该事务或更改 update/delete 语句的隔离级别。
  READ COMMITED SNAPSHOT
  READ COMMITED SNAPSHOT也是基于行版本控制的。但是它与SANPSHOT不同的是,读取者获得的是“语句”启动时可用的后提交的行版本,而不是事务启动时可用的后提交的行版本。这种隔离级别不会检测更新冲突,但是如果所请求资源以排它锁方式锁定时,它不会请求共享锁并且不会等待。
  首先修改数据库设置,将READ COMMITED SNAPSHOT隔离级别打开:
  ALTER DATABASE dbname SET READ_COMMITED_SNAPSHOT ON;
  启动之后,隔离级别将隐式地更改为READ COMMITED SNAPSHOT
  在连接1运行如下事务:
  BEGIN TRAN;
  UPDATE Production.Products SET unitprice += 1.00 WHERE productid = 2;
  SELECT productid, unitprice FROM Production.Products WHERE productid = 2;
  运行后将得到:
  productid   unitprice
  ----------  ----------
  2            20.00
  在连接2中,打开一个事务并尝试读取产品2,并使事务处于打开状态:
  BEGIN TRAN;
  SELECT productid, unitprice FROM Production.Products WHERE productid = 2;
  运行后得到近提交的版本:
  productid   unitprice
  ----------  ----------
  2            19.00
  现在在连接1中提交事务:
  COMMIT TRAN;
  那么此时近提交的行版本发生了变化(20.00),如果此时在连接2中再次读取产品2的数据,并提交事务:
  SELECT productid, unitprice FROM Production.Products WHERE productid = 2;
  COMMIT TRAN;
  此时结果如下:
  productid   unitprice
  ----------  ----------
  2            20.00