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