我有一个在链接服务器上加入SQL Server表的视图。链接服务器存在某些限制,这意味着我无法在视图上创建索引,并且存在昨晚锁定数据库的存储过程,即使它只执行选择。存储过程由.NetTiers生成(我已从两个select语句中删除了十几列):
CREATE PROCEDURE [AbnormalReadingSource_Get]
(
@WhereClause varchar (2000) ,
@OrderBy varchar (2000) ,
@PageIndex int ,
@PageSize int
)
AS
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN
DECLARE @PageLowerBound int
DECLARE @PageUpperBound int
-- Set the page bounds
SET @PageLowerBound = @PageSize * @PageIndex
SET @PageUpperBound = @PageLowerBound + @PageSize
IF (@OrderBy is null or LEN(@OrderBy) < 1)
BEGIN
-- default order by to first column
SET @OrderBy = '[Result]'
END
-- SQL Server 2005 Paging
declare @SQL as nvarchar(4000)
SET @SQL = 'WITH PageIndex AS ('
SET @SQL = @SQL + ' SELECT'
IF @PageSize > 0
BEGIN
SET @SQL = @SQL + ' TOP ' + convert(nvarchar, @PageUpperBound)
END
SET @SQL = @SQL + ' ROW_NUMBER() OVER (ORDER BY ' + @OrderBy + ') as RowIndex'
SET @SQL = @SQL + ', [Result]'
SET @SQL = @SQL + ' FROM [AbnormalReadingSource]'
IF LEN(@WhereClause) > 0
BEGIN
SET @SQL = @SQL + ' WHERE ' + @WhereClause
END
SET @SQL = @SQL + ' ) SELECT'
SET @SQL = @SQL + ' [Result],'
SET @SQL = @SQL + ' FROM PageIndex'
SET @SQL = @SQL + ' WHERE RowIndex > ' + convert(nvarchar, @PageLowerBound)
IF @PageSize > 0
BEGIN
SET @SQL = @SQL + ' AND RowIndex <= ' + convert(nvarchar, @PageUpperBound)
END
exec sp_executesql @SQL
-- get row count
SET @SQL = 'SELECT COUNT(*) as TotalRowCount'
SET @SQL = @SQL + ' FROM [AbnormalReadingSource]'
IF LEN(@WhereClause) > 0
BEGIN
SET @SQL = @SQL + ' WHERE ' + @WhereClause
END
exec sp_executesql @SQL
END
数据库事务隔离级别为READ COMMITTED
,因此不必在存储过程中设置隔离级别,而是在用于生成存储过程的.NetTiers模板中。我可以使用 readpast 提示来避免发生锁定吗?使用 readpast 时,是否需要提供任何其他提示?
答案 0 :(得分:2)
您可以尝试使用READPAST,但请记住它不会允许“脏”读取,因此如果某些内容暂时被锁定,您的结果集可能会遗漏某些记录。
同样,您可以尝试使用以下选择语句:WITH(NOLOCK)
NOLOCK将读取“脏”数据,但之后您将面临被回滚的风险。
两者都会避免阻塞,两者都有其优点和缺点。
本文应有助于澄清:
http://www.techrepublic.com/article/using-nolock-and-readpast-table-hints-in-sql-server/6185492
答案 1 :(得分:2)
与此查询一起运行 SQL事件探查器,然后将其提供给数据库引擎优化顾问。如果您可以解决此问题或改进索引,请不要更改隔离级别。
您可以在链接服务器上创建视图,但这些链接服务器必须都是SQL Server ,并且索引视图中不允许跨数据库查询。
也许这个程序不应该通过视图运行。
http://msdn.microsoft.com/en-us/library/ms191432.aspx
很棒的锁定文章
http://support.microsoft.com/kb/75722 http://support.microsoft.com/kb/323630
不要在存储过程中使用单词sp,那些为系统存储过程保留会导致较小的开销。
游标很糟糕,但更好的索引是主要的解决方案,当然Tuning Advisor会自动为您编写脚本,这意味着您需要完全绕过视图来利用。
创建有关此流程的故障警报,以便您和您的联合经理在您通过SSIS SMTP任务离开办公室时知道此任务是否失败。
“要从其他服务器重复获取数据,创建链接服务器,然后使用OPENQUERY函数或使用4部分命名。如果您不遵守T-SQL,那么最好使用导入/导出向导,并且您可以将其保存为SSIS包以供将来使用。“ - SQL Server MVP Pinal Dave
关于锁定和潜在的死锁
您可以用来解决死锁的典型方法包括:
保持交易尽可能短。
在SQL Server中,您还可以使用以下任一方法最小化锁定争用,同时保护事务免受未提交数据修改的脏读:
加载SQL事件探查器,重点关注锁定,启动专门针对该数据库的死锁脚本并将其提供给数据库引擎优化顾问,并查看建议。
<强>脚注强>: http://support.microsoft.com/kb/832524
[[1]:http://support.microsoft.com/kb/832524
http://www.codeproject.com/Articles/42547/SQL-SERVER-How-To-Handle-Deadlock
之前的Stackoverflow锁定问题how to solve deadlock problem?
答案 2 :(得分:1)
为什么不把TRANSACTION ISOLATION LEVEL设置为READ UNCOMMITTED
,你几乎可以得到与使用READPAST或NOLOCK相同的结果
我知道你说过程是由.NetTiers生成的,但既然你说你可以添加一个查询提示(readpast),我假设你也可以改变隔离级别。