一、脏读、不可重复读、幻象读的区别
1、脏读:包含未提交数据的读取。例如,事务 a 更改了某行(数据库已发生更改,但尚未提交,有可能发生回滚),事务 b 在事务 a 提交更改之前读取已更改的行。如果事务 a 回滚更改,则事务 b 读取到了不存在的脏数据
2、不可重复读取:当某个事务(a)不止一次读取同一行,并且一个单独的事务(b)在两次或多次读取之间修改了该行,所以事务(a)每次读取的该行的值都不同。
3、幻象:是指当事务不是独立执行时发生的一种现象。例如当事务(a)对一个表中的数据进行全部修改时,第二个事务(b)向表中插入一行新数据。则事务(a)发现表中还有没修改的数据,如同发生了幻觉一样。
二、SQL Server 锁类型
1、共享锁:用于只读操作(select),锁定共享的资源。共享锁不会阻止其他用户读,但是阻止其他用户的写和修改,以避免脏读
2、更新锁:更新锁是一种意图锁,当一个事务已经请求共享锁后并试图请求一个独占锁的时候发生更新锁。例如当两个事务在几行数据行上都使用了共享锁,并同时试图获取独占锁以执行更新操作时,就发生了死锁,都在等待对方释放共享锁而实现独占锁。更新锁的目的是只让一个事务获得更新锁,防止这种情况发生。
3、独占锁:一次只能有一个独占锁用在一个资源上,并且阻止其他所有的锁包括共享锁。写是独占锁,可以有效的防止“脏读”。
4、意图锁:在使用共享锁和独占锁之前,使用意图锁。从表的层次上产看意图锁,以判断事物能否获取共享锁和独占锁,提供了系统的性能,不需从页或者行上检查。
5、计划锁:Sch-M,Sch-S。对数据库结构改变时用Sch-M,对查询进行编译时使用Sch-S。这两种锁不会阻塞任何事物锁,包括独占锁。
三、 .net 提供的数据库事务隔离级别 System.Data.IsolationLevel 枚举用于指定连接的事务锁行为,包含如下枚举:
成员名称 | 成员名称 | 说明 |
Chaos | 混乱 | 无法改写隔离级别更高的事务中的挂起的更改 |
ReadUncommitted | 未提交读 | 可以进行脏读,意思是说,不发布共享锁,也不接受独占锁 |
ReadCommitted | 提交读 | 在正在读取数据时保持共享锁,以避免脏读,但是在事务结束之前可以更改数据,从而导致不可重复的读取或幻象数据 |
RepeatableRead | 可重复读 | 在查询中使用的所有数据上放置锁,以防止其他用户更新这些数据。防止不可重复的读取,但是仍可以有幻象行 |
Serializable | 可串行读 | 在DataSet 上放置范围锁,以防止在事务完成之前由其他用户更新行或向数据集中插入行 |
Snapshot | 快照 | 通过在一个应用程序正在修改数据时存储另一个应用程序可以读取的相同数据版本来减少阻止。表示您无法从一个事务中看到在其他事务中进行的更改,即便重新查询也是如此。 |
Unspecified | 未指定的 | 正在使用与指定隔离级别不同的隔离级别,但是无法确定该级别。当使用OdbcTransaction 时,如果不设置IsolationLevel 或者将 IsolationLevel 设置为Unspecied,事务将根据基础ODBC驱动程序的默认隔离级别来执行。 |