我们正试图拥有一个只需要定期插入新记录的事务表.
这个简单的表需要我们随着时间的推移不断添加新的记录.此表中的事务量预计相当高,并且也可能需要几秒钟才能完成定期的事务批量导入(> 1000).
从这些数据中,我们然后执行一组select语句,将不同的列分组以返回所需的值.
从我们的初始测试中,我们发现与sql Server相关的瓶颈,阻止我们的SELECT在INSERTS事务中间.
下面是一个简单的例子,可以运行来说明问题.
– 简单DB表
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;
我希望Query 2直接返回,0到查询1完成,然后显示2.我们从不想看到从第二个查询返回1.
我们已经看过的答案与SELECT(NOLOCK)在select语句中相关.但是这违反了交易界限,返回的信息可能是财务性质的,我们不希望在我们的查询中看到任何不合规的细节.
我的问题似乎在INSERT方面…
为什么INSERT阻止SELECT语句即使不修改任何现有数据?
奖金积分问题:这是sql Server的“功能”,还是我们会在其他数据库中找到这个?
UPDATE
我现在有时间找到一个本地的oracle数据库,并运行相同的简单测试.这个测试通过我的预期.
那么我可以像我想要的那样经常运行查询,它将返回null直到第一个事务提交,然后返回2.
有没有办法让sql Server这样工作?还是我们需要迁移到Oracle?
解决方法
此锁定行为是sql Server的一项功能.
使用2005年及以上版本,您可以使用 row level versioning(这是Oracle上默认使用的)来实现相同的结果&不阻止你的选择.这会给tempdb带来额外的压力,因为tempdb维护了行级版本控制,因此请确保适应这种情况.
要使sql以您想要的方式运行,请运行以下命令:
使用2005年及以上版本,您可以使用 row level versioning(这是Oracle上默认使用的)来实现相同的结果&不阻止你的选择.这会给tempdb带来额外的压力,因为tempdb维护了行级版本控制,因此请确保适应这种情况.
要使sql以您想要的方式运行,请运行以下命令:
ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON