【发布时间】:2009-04-27 04:28:55
【问题描述】:
我们正在尝试创建一个只接受定期插入的新记录的事务表。
这个简单的表需要我们随着时间的推移不断地向它添加新记录。此表中的交易量预计会非常高,并且可能会定期批量导入交易(>1000),这可能需要几秒钟才能完成。
然后我们根据这些数据执行一组选择语句,将不同的列分组以返回所需的值。
从我们最初的测试中,我们发现了一个与 SQL Server 相关的瓶颈,它在 INSERTS 事务的中间阻塞了我们的 SELECT。
下面是一个简单的例子,可以用来说明问题。
-- 简单数据库表
create table LOCK_TEST (
LOCK_TEST_ID int identity ,
AMOUNT int);
-- 在 1 个查询窗口中运行它
begin tran
insert into LOCK_TEST (AMOUNT) values (1);
WAITFOR DELAY '00:00:15' ---- 15 Second Delay
insert into LOCK_TEST (AMOUNT) values (1);
commit
-- 在查询 2 中并行运行
select SUM(AMOUNT)
from LOCK_TEST;
我希望查询 2 立即返回,在查询 1 完成之前返回 0,然后显示 2。我们绝不希望看到从第二个查询返回 1。
我们看到的答案与 select 语句中的 WITH (NOLOCK) 相关。但这违反了交易边界,返回的信息可能是财务性质的,我们不希望在查询中看到任何未提交的细节。
我的问题似乎出在 INSERT 方面...
为什么 INSERT 会阻止 SELECT 语句,即使它没有修改任何现有数据?
加分问题:这是 SQL Server 的“功能”,还是我们也会在其他数据库类型中找到此功能?
更新 我现在有时间找到一个本地 oracle 数据库并运行相同的简单测试。正如我所料,这次测试通过了。
也就是说,我可以根据需要多次运行查询,它会在第一个事务提交之前返回 null,然后返回 2。
有没有办法让 SQL Server 像这样工作?还是我们需要迁移到 Oracle?
【问题讨论】:
-
这些表上有哪些索引?你们有定期的索引维护吗?
-
目前没有索引。看这篇博文中列出的简单例子,无非就是简单的2列表,基本的insert和select都是用来重现这个问题的。
标签: sql-server sql-server-2008