Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Tự động xóa các quy trình bị mắc kẹt trong MS SQL Server

Giới thiệu

Có những tình huống khi các ứng dụng giữ kết nối cơ sở dữ liệu trong một thời gian dài. Nó dường như không quan trọng. Tuy nhiên, nếu ứng dụng này tạo nhiều kết nối hoặc có một số ứng dụng có hành vi như vậy - mọi thứ sẽ trở nên tồi tệ hơn.

Bài viết này không phải là một hướng dẫn. Nó mô tả các giải pháp khả thi cho vấn đề này. Như thường lệ, tôi rất vui khi biết bất kỳ giải pháp thay thế nào.

Giải pháp

1. Tạo một thủ tục được lưu trữ đóng tất cả các kết nối hoặc kết nối của một người dùng nhất định với cơ sở dữ liệu được chỉ định:

USE [DATABASE_NAME]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [srv].[KillConnect]
    @databasename nvarchar(255), -- database
    @loginname    nvarchar(255)=NULL  -- login details
AS
BEGIN
    /*
     deletes connections for the specified database and login details access
    */
    SET NOCOUNT ON;
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

    if(@databasename is null)
    begin
        ;THROW 50000, 'A database is not specified!', 0;
    end
    else
    begin
        declare @dbid int=db_id(@databasename);

        if(@dbid is NULL)
        begin
            ;THROW 50000, 'The database does not exist!', 0;
        end
        else if @dbid <= 4
        begin
            ;THROW 50000, 'To delete connections to a system database is forbidden!', 0;
        end
        else
        begin
            declare @query nvarchar(max);
            set @query = '';

            select @query=coalesce(@query,',' )
                        +'kill '
                        +convert(varchar, spid)
                        +'; '
            from master..sysprocesses
            where dbid=db_id(@databasename)
            and spid<>@@SPID
            and ([email protected] or @loginname is null);

            if len(@query) > 0
            begin
                begin try
                    exec(@query);
                end try
                begin catch
                end catch
            end
        end
    end
END

GO

Quy trình được lưu trữ này giúp vô hiệu hóa thủ công tất cả các kết nối với cơ sở dữ liệu hoặc một người dùng nhất định để thực hiện các hành động tiếp theo với cơ sở dữ liệu.

2. Tạo một quy trình được lưu trữ để xóa tất cả các quy trình bị mắc kẹt.

USE [DATABASE_NAME]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [srv].[KillFullOldConnect]
AS
BEGIN
    /*
       It deletes the connections which were executed a day ago. 
       Attention! System databases such as master, tempdb, model and msdb 
       do not take part in this process. 
       However, it does not affect database distribution for replication.
    */
    SET NOCOUNT ON;
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

    declare @query nvarchar(max);
    set @query = '';

    select @query=coalesce(@query,',' )
                +'kill '
                +convert(varchar, spid)
                +'; '
    from master..sysprocesses
    where dbid>4
    and [last_batch]<dateadd(day,-1,getdate())
    order by [last_batch]

    if len(@query) > 0
    begin
        begin try
            exec(@query);
        end try
        begin catch
        end catch
    end
END
GO

Thủ tục được lưu trữ này sẽ xóa các kết nối đã được hoàn thành hơn 24 giờ trước. Ngoài ra, thủ tục này không ảnh hưởng đến cơ sở dữ liệu hệ thống chính (master, tempdb, model và msdb). Nếu bạn cố gắng truy cập cơ sở dữ liệu trong khi kết nối bị tắt, một kết nối mới cho ứng dụng này sẽ được tạo.

Bây giờ, cần phải chạy một thủ tục được lưu trữ trong tác vụ Tác nhân mỗi ngày một lần:

exec [DATABASE_NAME].[srv].[KillFullOldConnect];

Sẽ tốt hơn nếu gói truy vấn này vào khối try-catch để xử lý một lệnh gọi ngoại lệ có thể xảy ra.

Kết quả

Trong bài viết này, tôi đã phân tích cách triển khai các thủ tục được lưu trữ khi đóng kết nối với cơ sở dữ liệu (tất cả hoặc một người dùng nhất định) và xóa các quy trình bị mắc kẹt trên một ví dụ cụ thể. Ngoài ra, tôi đã khám phá một ví dụ cụ thể về cách tự động chạy một tác vụ khi xóa các quy trình bị mắc kẹt hàng ngày. Nó cho phép giảm số lượng kết nối "chết" đến máy chủ. Việc xóa tất cả các kết nối đến cơ sở dữ liệu cho phép bạn sửa đổi một số thuộc tính, cũng như đóng quá trình gây ra bất kỳ sự cố nào.

Tài liệu tham khảo:

»Hệ thống xử lý
» tiêu diệt
»db_id
» @@ SPID


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. @@ LỖI và / hoặc THỬ - CATCH

  2. Làm cách nào để tiện ích mở rộng SQLSRV hoạt động với PHP, vì MSSQL không được dùng nữa?

  3. Cách hàm RIGHT () hoạt động trong SQL Server (T-SQL)

  4. Cách khôi phục cơ sở dữ liệu từ C #

  5. Lưu trữ và phân tích tài liệu trên hệ thống tệp Windows với Tìm kiếm ngữ nghĩa SQL Server - Phần 2