Frequent blocking in Nav on SQL Server

afarr
Member Posts: 287
Our client has started experiencing lots of blocking, which is slowing down their system.
They only noticed this on Tuesday, it wasn’t an issue before that.
The blocking happens several times a minute, for just a few seconds each time.
It is experienced by many different users, in different areas of Navision, with no noticeable pattern.
In all cases, in the session table, the userID is the same as the “blocking user ID” (i.e. the user seems to be blocking their own ID), and the “blocking object” is blank.
So it is not clear what to investigate (and besides, no objects were modified in the last 12 days).
I sent the clie a document with several different suggestions (e.g. turning off “Find As You Type”, ensuring that there is sufficient free space, running SQL maintenance jobs regularly, turning off AutoCostPosting, etc.). They said that they implemented many of the suggestions without seeing any improvement.
ChangeLog is only activated on two tables, which are part of an add-on.
They are using Nav 3.70 B on SQL 2000, with a 60 GB database.
How can we find what is causing the blocking, when there is no blocking object (and no other user ID) mentioned?
Thanks,
Alastair
They only noticed this on Tuesday, it wasn’t an issue before that.
The blocking happens several times a minute, for just a few seconds each time.
It is experienced by many different users, in different areas of Navision, with no noticeable pattern.
In all cases, in the session table, the userID is the same as the “blocking user ID” (i.e. the user seems to be blocking their own ID), and the “blocking object” is blank.
So it is not clear what to investigate (and besides, no objects were modified in the last 12 days).
I sent the clie a document with several different suggestions (e.g. turning off “Find As You Type”, ensuring that there is sufficient free space, running SQL maintenance jobs regularly, turning off AutoCostPosting, etc.). They said that they implemented many of the suggestions without seeing any improvement.
ChangeLog is only activated on two tables, which are part of an add-on.
They are using Nav 3.70 B on SQL 2000, with a 60 GB database.
How can we find what is causing the blocking, when there is no blocking object (and no other user ID) mentioned?
Thanks,
Alastair
Alastair Farrugia
0
Comments
-
Have you tried and reboot the sql server?0
-
Hi,
maybe this could help you a little:
http://dynamicsuser.net/blogs/stryk/archive/2008/11/03/blocks-amp-deadlocks-in-nav-with-sql-server.aspx
But this actually refers to SQL Server 2005 and up.
With SQL 2000 you have very limited options in recording blocks & deadlocks; maybe you could create a table ...if not exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[ssi_BlockCheck_Tab]') and objectproperty(id, N'IsTable') = 1) create table [dbo].[ssi_BlockCheck_Tab] ( [entry_no] bigint identity constraint [ssi_BlockCheck_Tab$pk_ci] primary key clustered, [timestamp] datetime, [db] varchar(128) collate database_default, [waitresource] varchar(128), [table_name] varchar(128) collate database_default, [index_name] varchar(128) collate database_default, [waittime] bigint, [lastwaittype] varchar(128), [spid] int, [loginame] varchar(128) collate database_default, [hostname] varchar(128) collate database_default, [program_name] varchar(128) collate database_default, [cmd] nvarchar(255) collate database_default, [status] varchar(128) collate database_default, [cpu] bigint, [lock_timeout] int, [blocked by] int, [loginame 2] varchar(128) collate database_default, [hostname 2] varchar(128) collate database_default, [program_name 2] varchar(128) collate database_default, [cmd 2] nvarchar(255) collate database_default, [status 2] varchar(128) collate database_default, [cpu 2] bigint, [block_orig_id] int, [block_orig_loginame] varchar(128) collate database_default ) go
... then a stored procedure to save the block data ...create procedure dbo.ssi_blockcheck @mode varchar(10) = 'loop', -- "loop" or "once" @threshold int = 1000, -- Block threshold in milliseconds @frequency int = 3, -- Check frequency in milliseconds @save tinyint = 1 -- save output to table ssi_BlockCheck_Tab (0 = no, 1 = yes) --with encryption as if (@mode not in ('loop', 'once')) begin raiserror ('ERROR: Invalid Parameter @mode: %s', 15, 1, @mode) return end if (@threshold < 1) begin raiserror ('ERROR: Invalid Parameter @threshold: %i', 15, 1, @threshold) return end if (@frequency < 1) begin raiserror ('ERROR: Invalid Parameter @frequency: %i', 15, 1, @frequency) return end if (@save not in (0,1)) begin raiserror ('ERROR: Invalid Parameter @save: %i', 15, 1, @save) return end set nocount on set statistics io off declare @spid int, @spid2 int, @loginame varchar(128), @blocked_by int, @blocked_by_name varchar(128), @orig_id int, @orig_name varchar(128), @timestmp datetime, @i int if @mode = 'once' goto start_check while 1 = 1 begin start_check: if exists (select * from master..sysprocesses where [blocked] <> 0) begin if @save = 0 begin select [db] = db_name(s1.[dbid]), ltrim(rtrim(s1.[waitresource])), [table_name] = object_name(sl.rsc_objid), [index_name] = si.[name], s1.[waittime], s1.[lastwaittype], s1.[spid], s1.[loginame], s1.[hostname], s1.[program_name], s1.[cmd], s1.[status], s1.[cpu], [blocked by] = s1.[blocked], [loginame 2] = s2.[loginame], [hostname 2]=s2.[hostname], [program_name 2] = s2.[program_name], [cmd 2] = s2.[cmd], s2.[status], s2.[cpu] -- Processes from master..sysprocesses s1 (nolock) left outer join master.dbo.sysprocesses s2 (nolock) on s1.[blocked] = s2.[spid] -- Lock-Info left outer join master.dbo.syslockinfo sl (nolock) on s1.[spid] = sl.[req_spid] -- Indexes left outer join sysindexes si (nolock) on sl.rsc_objid = si.[id] and sl.rsc_indid = si.[indid] where s1.[blocked] <> 0 and (sl.rsc_type in (4,5,6,7)) and sl.rsc_indid <> 0 and sl.req_status = 3 and s1.[waittime] >= @threshold end else begin set @timestmp = getdate() create table #dbcc_inputbuffer (EventType nvarchar(30), Parameter int, EventInfo nvarchar(255)) insert into [ssi_BlockCheck_Tab] ([timestamp],[db],[waitresource],[table_name],[index_name],[waittime], [lastwaittype],[spid],[loginame],[hostname],[program_name], [cmd],[status],[cpu],[blocked by],[loginame 2],[hostname 2],[program_name 2],[cmd 2],[status 2],[cpu 2],[block_orig_id],[block_orig_loginame]) select @timestmp, [db] = db_name(s1.[dbid]), ltrim(rtrim(s1.[waitresource])), [table_name] = object_name(sl.rsc_objid), [index_name] = si.[name], s1.[waittime], s1.[lastwaittype], s1.[spid], s1.[loginame], s1.[hostname], s1.[program_name], s1.[cmd], s1.[status], s1.[cpu], [blocked by] = s1.[blocked], [loginame 2] = s2.[loginame], [hostname 2]=s2.[hostname], [program_name 2] = s2.[program_name], [cmd 2] = s2.[cmd], s2.[status], s2.[cpu], null, null -- Processes from master..sysprocesses s1 (nolock) left outer join master.dbo.sysprocesses s2 (nolock) on s2.[spid] = s1.[blocked] -- Lock-Info left outer join master.dbo.syslockinfo sl (nolock) on s1.[spid] = sl.req_spid -- Indexes left outer join sysindexes si (nolock) on sl.rsc_objid = si.[id] and sl.rsc_indid = si.[indid] where s1.[blocked] <> 0 and (sl.rsc_type in (4,5,6,7)) and sl.rsc_indid <> 0 and sl.req_status = 3 and s1.[waittime] >= @threshold -- updating [cmd] from DBCC INPUTBUFFER declare spid_cur cursor for select [spid], [blocked by] from [dbo].[ssi_BlockCheck_Tab] where [timestamp] = @timestmp for update open spid_cur fetch next from spid_cur into @spid, @blocked_by while @@fetch_status = 0 begin -- SPID insert into #dbcc_inputbuffer exec('DBCC INPUTBUFFER (' + @spid + ') WITH NO_INFOMSGS') update [ssi_BlockCheck_Tab] set [cmd] = (select [EventInfo] from #dbcc_inputbuffer) where current of spid_cur delete from #dbcc_inputbuffer -- BLOCKED BY insert into #dbcc_inputbuffer exec('DBCC INPUTBUFFER (' + @blocked_by + ') WITH NO_INFOMSGS') update [ssi_BlockCheck_Tab] set [cmd 2] = (select [EventInfo] from #dbcc_inputbuffer) where current of spid_cur delete from #dbcc_inputbuffer fetch next from spid_cur into @spid, @blocked_by end close spid_cur deallocate spid_cur drop table #dbcc_inputbuffer update [dbo].[ssi_BlockCheck_Tab] set [table_name] = '- unknown -' where [table_name] is null -- get block originator declare originator_cur cursor for select [blocked by], [loginame 2] from [dbo].[ssi_BlockCheck_Tab] where [timestamp] = @timestmp for update open originator_cur fetch next from originator_cur into @blocked_by, @blocked_by_name while @@fetch_status = 0 begin set @i = 0 set @orig_id = @blocked_by set @orig_name = @blocked_by_name set @spid2 = @blocked_by while (@spid2 <> 0) and (@i < 100) begin if exists(select top 1 [blocked by] from [dbo].[ssi_BlockCheck_Tab] where ([timestamp] = @timestmp) and ([spid] = @spid2)) begin select top 1 @spid = [blocked by], @loginame = [loginame 2] from [dbo].[ssi_BlockCheck_Tab] where ([timestamp] = @timestmp) and ([spid] = @spid2) set @orig_id = @spid set @orig_name = @loginame set @spid2 = @spid end else set @spid2 = 0 set @i = @i + 1 -- "Emergency Exit", to avoid recursive loop end update [dbo].[ssi_BlockCheck_Tab] set [block_orig_id] = @orig_id, [block_orig_loginame] = @orig_name where current of originator_cur fetch next from originator_cur into @blocked_by, @blocked_by_name end close originator_cur deallocate originator_cur end end end_check: if @mode = 'once' return waitfor delay @frequency end
(Don't forget to install all this in you NAV database!)
Finally you could create a job which executes this TSQL query in the "Job Step":create procedure dbo.ssi_blockcheck @mode = 'loop', -- "loop" or "once" @threshold = 1000, -- Block threshold in milliseconds @frequency = 3, -- Check frequency in milliseconds @save = 1 -- save output to table ssi_BlockCheck_Tab (0 = no, 1 = yes)
(Run in context of your NAV database!)
This would start the SP in a loop mode which checks every 3 seconds if there are blocks of more than 1000 milliseconds (change parameters on demand); if some detected it will write the info into the table. Then you could run some further investigations about blocking issues ...
Caution: in some cases this block-detection could cause heavy load (I/O, CPU) on the system!
Also have in mind that several NAV client versions are affected with some bugs :bug: which also could increase blocking issues!
Hope this could help you a little.
ALL SCRIPTS ARE PROVIDED "AS IS". NO WARRANTY, NO GUARANTEE, NO SUPPORT. USE AT OWN RISK.Jörg A. Stryk (MVP - Dynamics NAV)
NAV/SQL Performance Optimization & Troubleshooting
STRYK System Improvement
The Blog - The Book - The Tool0 -
Jorg (and Rashed), many thanks for your detailed reply.
I talked to the client again. They clarified that this was not a sudden problem – performance has suffered for some time, and this week they thought of checking if any blocking was occurring, but it might have been happening before that.
They have restarted the SQL Server, and the blocking is still occurring at the same rate.
They are going to look at other actions (allowing pagelocks on SQL Server, creating missing indexes, implementing AWE, and possibly increasing their RAM from the current 4 GB).
We will see if these help with the performance.Alastair Farrugia0
Categories
- All Categories
- 73 General
- 73 Announcements
- 66.6K Microsoft Dynamics NAV
- 18.7K NAV Three Tier
- 38.4K NAV/Navision Classic Client
- 3.6K Navision Attain
- 2.4K Navision Financials
- 116 Navision DOS
- 851 Navision e-Commerce
- 1K NAV Tips & Tricks
- 772 NAV Dutch speaking only
- 617 NAV Courses, Exams & Certification
- 2K Microsoft Dynamics-Other
- 1.5K Dynamics AX
- 320 Dynamics CRM
- 111 Dynamics GP
- 10 Dynamics SL
- 1.5K Other
- 990 SQL General
- 383 SQL Performance
- 34 SQL Tips & Tricks
- 35 Design Patterns (General & Best Practices)
- 1 Architectural Patterns
- 10 Design Patterns
- 5 Implementation Patterns
- 53 3rd Party Products, Services & Events
- 1.6K General
- 1.1K General Chat
- 1.6K Website
- 83 Testing
- 1.2K Download section
- 23 How Tos section
- 252 Feedback
- 12 NAV TechDays 2013 Sessions
- 13 NAV TechDays 2012 Sessions