I have a view that joins SQL Server tables on linked servers. There are certain restrictions on linked servers that mean I can’t create an index on the view and there is a stored procedure that last night locked the database, even though it is only doing a select. The stored procedure is generated by .NetTiers (I’ve elided a dozen columns from both select statements):
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
The database transaction isolation level is READ COMMITTED so setting the isolation level in the stored procedure isn’t necessary but is in the .NetTiers templates used to generate the stored procedure. Can I use the readpast hint to avoid the locking that occurred? Do I need to provide any other hints when using readpast?
You could try READPAST but remember it will not allow “dirty” reads so your result set could be missing some records if something is momentarily locked.
Similarly you could try your select statement with:
WITH(NOLOCK)NOLOCK will read the “dirty” data but then you run the risk of it being rolled back.
Both will avoid blocking, both have their pros and cons.
This article should help clarify:
http://www.techrepublic.com/article/using-nolock-and-readpast-table-hints-in-sql-server/6185492