默认情况下,SQL Server的事务隔离级别是READ COMMITED。刚开始我理解这个模式就是读已经提交的,那也就是说并发一个事务去更新,一个事务查询同一条数据应该是像Mysql、Oracle不会加锁直接返回数据库已经提交的数据才对。但是SQL Server不是这样的。
SQLServer中有READ_COMMITTED_SNAPSHOT,这个才不会对读加锁,直接读取提交的快照。
事务隔离级别是确保数据一致性和并发控制的重要机制。SQL Server 提供了多种事务隔离级别,其中READ_COMMITTED_SNAPSHOT
(读已提交快照)是一个特别值得注意的选项,它在提高并发读取性能的同时,也带来了一些独特的特性和考量。本文将详细探讨READ_COMMITTED_SNAPSHOT
的作用、优势、潜在影响及配置建议,并附上官方文档链接,以供深入学习。
什么是READ_COMMITTED_SNAPSHOT?
READ_COMMITTED_SNAPSHOT
隔离级别是SQL Server中的一种事务处理模式,它改变了传统的READ_COMMITTED
隔离级别下读取数据的方式。在标准的READ_COMMITTED
级别,读取操作会加上锁来阻止其他事务修改正在读取的数据,这可能导致锁争用,影响并发性能。而启用READ_COMMITTED_SNAPSHOT
后,读取事务不再请求共享锁,而是访问一个数据行的快照版本,这个版本是在事务开始时就已经存在的数据状态。这种方式减少了锁的使用,从而提高了并发读取的性能。
主要优势
- 减少锁争用:由于不加锁读取,大大降低了并发事务之间的锁等待和阻塞,提高了系统的吞吐量。
- 非阻塞读取:即使其他事务正在修改数据,读取事务也能顺利进行,不会被阻塞。
- 简化编程模型:对于开发者来说,可以减少因锁定引发的异常处理逻辑,使得应用程序编写更加简单。
潜在影响
- tempdb使用增加:快照数据存储在
tempdb
中,因此tempdb
的大小和I/O负载可能会显著增加。 - 存储和内存需求上升:维护行版本会占用更多的存储空间和内存资源。
- 可能的数据不一致性:尽管名为“读已提交”,但实际读取的是事务开始时刻的数据快照,因此在高并发写入场景下,可能无法反映最新数据状态。
- 性能考量:对于写密集型应用,启用
READ_COMMITTED_SNAPSHOT
可能不如预期那样提升性能,因为额外的版本管理操作会带来开销。
官方文档链接
推荐直接参考微软官方文档:
结论
READ_COMMITTED_SNAPSHOT
隔离级别是提升并发读取性能的有效手段,特别是在读多写少的应用场景中。然而,它的采用需权衡利弊,特别是对tempdb
的管理和监控,以及对数据一致性的理解和接受程度。在决定启用此选项之前,应充分评估系统的特定需求、资源限制和业务逻辑,以确保最佳的性能与数据完整性平衡。
另外,不推荐在代码中使用select xx,oo from table_n(nolock)这种东西,也就是不要随便使用NOLock,官方也不推荐这么使用,除非你能接受它带来的负面影响,一句话它是脏读:读未提交的数据。一个事务正在修改,还未提交,另一个事务使用nolock就能查到,并且可能把数据上送传入其他系统,但是如果那个事务最终并未提交呢?那上送的这种数据就是无头案了。【官方也不推荐这么使用】