事务级别,nolock / readpast和并发

时间:2008-11-13 15:08:21

标签: sql-server optimization concurrency transactions locking

我们有一个系统同时插入来自多个站的大量数据,同时还暴露了数据查询接口。架构看起来像这样(抱歉格式不佳):

[SyncTable]
  SyncID
  StationID
  MeasuringTime


[DataTypeTable]
  TypeID
  TypeName


[DataTable]
  SyncID
  TypeID
  DataColumns...

数据插入在“同步”中完成并且像这样(我们只将数据插入系统,我们从不更新)

INSERT INTO SyncTable(StationID, MeasuringTime) VALUES (X,Y); SELECT @@IDENTITY

INSERT INTO DataTable(SyncID, TypeID, DataColumns) VALUES 
  (SyncIDJustInserted, InMemoryCachedTypeID, Data)
  ... lots (500) similar inserts into DataTable ...

查询就像这样(对于给定的站点,测量时间和数据类型)

SELECT SyncID FROM SyncTable WHERE StationID = @StationID 
                               AND MeasuringTime = @MeasuringTime 
SELECT DataColumns FROM DataTable WHERE SyncID = @SyncIDJustSelected
                                  AND DataTypeID = @TypeID

我的问题是我们如何将插入的事务级别和查询的NOLOCK / READPAST提示结合起来,以便:

  1. 我们在系统中最大化并发性,同时支持插入(我们需要存储大量数据,每秒高达2000+记录)
  2. 查询仅从“提交”同步返回数据(我们不希望结果集具有半插入同步或由于跳过锁而与某些跳过的条目同步)
  3. 我们不关心查询中是否包含“最新”数据,我们更关心“实时”和最新数据的一致性和响应性
  4. 这可能是非常矛盾的目标,可能需要高事务隔离级别,但我对所有技巧和优化感兴趣,以实现对插入和选择的高响应性。我很乐意详细说明是否需要更多细节来清除更多调整和技巧。

    更新:只需为将来的回复添加更多信息。我们最初在具有5+ TB存储空间的SAN网络上运行SQL Server 2005(可能在六个月内发布)。我不确定SAn设置的是什么类型的RAID以及我们可用的确切磁盘数量。

3 个答案:

答案 0 :(得分:1)

如果您正在运行SQL 2005及更高版本,请查看实现snapshot isolation。使用nolock无法获得一致的结果。

在SQL 2000上解决这个问题要困难得多。

答案 1 :(得分:1)

这是SQL Server 2005/2008 Enterprise的分区功能的一个很好的方案。您可以为每个StationID创建一个分区,每个StationID的数据可以进入自己的文件组(如果需要,可能不需要,具体取决于您的负载。)

这为您带来并发的一些优势:

  • 如果按stationid进行分区,则用户可以对当前未加载的stationid运行select查询,并且它们不会遇到任何并发问题
  • 如果按stationid进行分区,则多个工作站可以同时插入数据而不会出现并发问题(只要它们位于不同的文件组中)
  • 如果按syncid范围进行分区,则可以将旧数据放在速度较慢的存储上。
  • 如果您按同步范围进行分区,如果您的范围足够小(意味着不是包含数千个同步的范围),那么您可以在用户查询的同时执行加载而不会遇到并发问题

您描述的场景与数据仓库夜间加载有很多共同之处。微软做了一个名为Project Real的技术参考项目,你可能会感兴趣。他们将其作为标准发布,您可以阅读设计文档和实现代码,以了解它们如何实现快速加载:

http://www.microsoft.com/technet/prodtechnol/sql/2005/projreal.mspx

在SQL Server 2008中进行分区甚至更好,特别是在并发性方面。它仍然不是银弹 - 它需要熟练的DBA手动设计和维护。它不是一种“一劳永逸”的功能,它确实需要企业版,其成本高于标准版。不过我喜欢它 - 我已经多次使用过它,它解决了我的具体问题。

答案 2 :(得分:0)

  1. 您将使用哪种类型的磁盘系统?如果您有一个大条带RAID阵列,写入应该运行良好。如果您可以估算每秒所需的读写次数,则可以将这些数字插入公式中,看看您的磁盘子系统是否能跟上。也许你无法控制硬件......

  2. 您是否不会在事务中包装插入内容,这会使插入在插入完成之前无法读取?

  3. 如果您的硬件配置正确并且您正在关注您的SQL编码,那么应该遵循这一点 - 您似乎就是这样。

  4. 查看SQLIO.exe和SQL Stress工具:

    SQLIOStress.exe SQLIOStress.exe模拟SQL Server 2000 I / O行为的各种模式,以确保基本的I / O安全。

    可以从Microsoft网站下载SQLIOStress实用程序。请参阅以下文章。

    •如何使用SQLIOStress实用程序来强调SQL Server等磁盘子系统 http://support.microsoft.com/default.aspx?scid=kb;en-us;231619

    重要下载内容包含一份完整的白皮书,其中包含有关该实用程序的详细信息。

    SQLIO.exe SQLIO.exe是一个SQL Server 2000 I / O实用程序,用于建立基本的基准测试结果。

    可以从Microsoft网站下载SQLIO实用程序。请参阅以下内容: •SQLIO性能测试工具(SQL开发) - 客户可用 http://download.microsoft.com/download/f/3/f/f3f92f8b-b24e-4c2e-9e86-d66df1f6f83b/SQLIO.msi