我有一个带有nvarchar(50)列的SQL Server表。此列必须是唯一的,并且不能是PK,因为另一列是PK。所以我在这个列上设置了一个非聚集的唯一索引。
在可序列化事务中的大量insert语句中,我想在不同的事务中仅基于此列执行select查询。但这些插件似乎锁定了桌子。例如,如果我将unique列的数据类型更改为bigint,则不会发生锁定。
为什么nvarchar不工作,而bigint呢?如何使用nvarchar(50)作为数据类型来实现相同的目标?
答案 0 :(得分:2)
毕竟,神秘解决了!相当愚蠢的情况,我猜..
问题出在select语句中。 where子句缺少引号,但是由于现有数据的错误巧合只是数字,所以选择没有失败,但只是在插入提交之前没有执行。插入第一个字母数字数据后,选择语句开始失败,并且错误地将数据类型nvarchar转换为数字'
e.g 而不是
SELECT [my_nvarchar_column]
FROM [dbo].[my_table]
WHERE [my_nvarchar_column] = '12345'
select语句是
SELECT [my_nvarchar_column]
FROM [dbo].[my_table]
WHERE [my_nvarchar_column] = 12345
我想进行了一次无声演员表演,没有使用唯一的索引导致该块。 修正了声明,现在一切正常。
感谢大家的帮助,对这个相当愚蠢的问题感到抱歉!
答案 1 :(得分:1)
首先,您可以将PK更改为非聚集索引,然后您可以在此字段上创建聚簇索引。当然,根据您的使用情况,这可能是一个坏主意,或者只是没有帮助。
您可能有覆盖索引的用例,请参阅上一页question re: covering index
您可以更改其他查询"通过更改这些查询的隔离级别来实现非阻塞。
在单个事务中插入大量行是必要的。您可以简单地不使用事务,或者拆分成较小的事务集以避免锁定表的大部分。例如,您可以将记录插入到事务中的挂起表(在正常活动中未使用),然后如果不需要实时发布到主表,则将较小事务中的这些记录迁移到主表。 / p>
ADDED
也许是最明显的问题。您确定必须使用可序列化的事务来插入大量记录吗?在金融交易之外,这些相对很少是必要的,与其他隔离级别相比,它们的并发成本较高?
ADDED
根据您关于"全部或没有"的评论,您描述的是原子性,而不是可序列化。也就是说,您可以为大型插入事务使用不同的隔离级别,并且仍然具有原子性。
第二件事,我注意到你指定了大量的insert语句。这听起来好像您应该能够将这些插入推送到挂起/临时表中,然后从登台表执行单个插入或批量插入到生产表中。是的,这是更多的工作,但你可能只是有一个需要额外努力的现有问题。
答案 2 :(得分:0)
您可能希望将NOLOCK提示(a.k.a. READUNCOMMITTED)添加到您的查询中。它将允许对已经插入的数据执行“脏读”。
e.g。
SELECT
[my_nvarchar_column]
FROM
[dbo].[locked_table] WITH (NOLOCK)
在这里看一个更好的解释:
http://www.mssqltips.com/sqlservertip/2470/understanding-the-sql-server-nolock-hint/
这里的READUNCOMMITTED部分: