Question

I have some processes that are taking long time to terminate.

I had run q query that took 30 hours "I forgot about it" so I killed it using "kill id" but it has been trying to roll back for more than 30 hours already.

Can someone please tell me how can I force this to stop?

when I run this query

select
    p.spid
,   right(convert(varchar, 
            dateadd(ms, datediff(ms, P.last_batch, getdate()), '1900-01-01'), 
            121), 12) as 'batch_duration'
,   P.program_name
from master.dbo.sysprocesses P
where P.spid > 50
and      P.status not in ('background', 'sleeping')
and      P.cmd not in ('AWAITING COMMAND'
                    ,'MIRROR HANDLER'
                    ,'LAZY WRITER'
                    ,'CHECKPOINT SLEEP'
                    ,'RA MANAGER')
order by batch_duration desc

I get the following results

61  23:40:48.893    Microsoft SQL Server Management Studio - Query                                                                                  
51  23:33:03.410    Microsoft SQL Server Management Studio - Query                                                                                  
58  23:01:08.960    Microsoft SQL Server Management Studio - Query                                                                                  
55  20:45:41.953    Microsoft SQL Server Management Studio - Query                                                                                  
64  19:08:37.310    Microsoft SQL Server Management Studio - Query                                                                                  
62  00:00:05.207    Microsoft SQL Server Management Studio - Query    

When I run kill 61 I get the following SPID 61: transaction rollback in progress. Estimated rollback completion: 0%. Estimated time remaining: 0 seconds. (this has been the case for the past 24 hours!)

What can I do to fix this problem?

Thanks

Was it helpful?

Solution 2

If you want to kill all the processes, may be, the fastest way is:

ALTER DATABASE [Data base name] SET SINGLE_USER WITH ROLLBACK IMMEDIATE

After that may be you want to go back to the previous database state:

ALTER DATABASE [Data base name] SET MULTI_USER

That is going to kill all the processes without restarting the server. If you want to kill a set of specific processes and "kill @spid" doesnt work I can only recomend you to use a DAC connection and see what happens.

OTHER TIPS

You're just going to have to wait. Some people panic and pull the power cord, but this will likely just mean the rollback will start over once you restart the service.

You may want to look at this Connect item for potential workarounds (and confirmation that this is a known issue and won't likely be fixed any time soon):

http://connect.microsoft.com/SQLServer/feedback/details/187192/openquery-to-linked-server-hangs...

As an aside, a few things about your query:

  1. You should only be using sysprocesses if you are using SQL Server 2000 or older. From SQL Server 2005 on you should be using DMVs (e.g. sys.dm_exec_requests). The old sys... views still exist for backward compatibility only. However, in some cases, you may want to use it to determine the waitresource - it may provide information about the remote instance / session, depending on the linked server type, which may give you information you can use to kill the process on the other end. In your case this isn't relevant because the remote "server" is just a text file. Perhaps you can kill the task with Task Manager...

  2. spid > 50 is not a very foolproof way to identify non-system processes. The new DMVs, for example, allow you to identify user processes using sys.dm_exec_sessions.is_user_process.

  3. You should not CONVERT(VARCHAR without specifying a length.

  4. You should not use shorthand like ms - if you mean MILLISECOND, type MILLISECOND. And do you really need millisecond accuracy when measuring a query that has been running for 30 hours?

  5. Be very careful with 'string delimited column aliases' - this syntax is deprecated in some cases and also looks like a string literal to most readers. If you really want to delimit the alias (in this case you don't need to), use [square brackets].

  6. Your truncation of the time only makes little sense to me. If the query had been running for four days, you wouldn't know. Why not:

    ;WITH x AS 
    (
      SELECT 
        session_id, 
        command,
        [status],
        s = DATEDIFF(SECOND, start_time, CURRENT_TIMESTAMP)
      FROM sys.dm_exec_requests AS r
      WHERE EXISTS 
      (
        SELECT 1 FROM sys.dm_exec_sessions 
        WHERE session_id = r.session_id
        AND is_user_process = 1
      )
      AND start_time < DATEADD(HOUR, -1, CURRENT_TIMESTAMP)
    )
    SELECT session_id, command, [status], s,
      CONVERT(VARCHAR(12), s / 86400) + ' days '
      + CONVERT(VARCHAR(2), (s % 86400) / 3600) + ' hours '
      + CONVERT(VARCHAR(2), (s % 86400) % 3600 / 60) + ' minutes.'
    FROM x
    ORDER BY s DESC;
    

You can't avoid the ROLLBACK. You should try to avoid to start it instead. Do I understand there are 3 copies of the same code running ???

Maybe you can use a SEMAPHORE check before running it. For example:

Check if a temp table exist before running the 30h code. If the table exists you don't run the code else you create the table THEN you run the code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top