sql >> Database teknologi >  >> RDS >> Sqlserver

Automatisk sletning af glemte transaktioner i MS SQL Server

Introduktion

Det er ofte tilfældet, når en MS SQL Server-transaktion bliver glemt af initiativtageren. Det bedste eksempel ville være følgende:et script udføres i SSMS, som via 'begin tran' instruktionen starter en transaktion, og der opstår en fejl; dog går 'commit' eller 'rollback' ikke igennem, og udførelsesinitiatoren har forladt denne forespørgsel i lang tid. Som følge heraf opstår der flere og flere udsving, når det kommer til at blokere de forespørgsler, der anmoder om adgang til lukkede ressourcer (tabeller og serverressourcer såsom RAM, CPU og input-output-systemet).

I denne artikel vil vi se på en af ​​måderne, hvorpå du kan automatisere processen for sletning af glemte transaktioner.

Løsningen

Lad os definere en glemt transaktion som en aktiv (aktuelt udført) transaktion, der i et tilstrækkeligt stort tidsrum T ikke har nogen aktive (aktuelt udførte) forespørgsler.

Her er den generelle algoritme til sletning af sådanne transaktioner:

  1. Oprettelse af en tabel til at gemme og analysere information om aktuelt glemte transaktioner samt en tabel til at sortere og arkivere de transaktioner, der er valgt fra den første tabel ved hjælp af sletningshandlinger.
  2. Indsamling af information (transaktioner og deres sessioner, der ikke har nogen forespørgsler, dvs. de transaktioner, der er blevet udført og glemt inden for et specificeret tidsrum T.
  3. Opdatering af tabellen, der indeholder alle aktuelt glemte transaktioner, vi fik i trin 1 (hvis en glemt transaktion har erhvervet en aktiv forespørgsel, vil en sådan transaktion blive slettet fra denne tabel).
  4. Hentning af de sessioner, vi skal dræbe (en session har mindst én transaktion, der blev placeret som glemt i tabellen fra trin 1 K eller flere gange, og sessionen havde en manglende aktiv forespørgsel det samme antal gange).
  5. Arkivering af de data, som vi vil slette (detaljer om sessioner, forbindelser og transaktioner, der vil blive dræbt).
  6. Sletter de valgte sessioner.
  7. Sletning af de behandlede poster sammen med dem, der ikke kan fjernes og har været i tabellen fra trin 1 for længe.

Lad os nu se, hvordan vi kan implementere denne algoritme.
Først og fremmest skal vi oprette en tabel til at gemme og analysere oplysningerne om alle aktuelt glemte transaktioner:

BRUG [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[SessionTran]( [SessionID] [int] IKKE NULL, [Transaktions-ID] [bigint] IKKE NULL, [CountTranNotRequest NOT] [tinyintRequest] [tinyintRequest] ] [tinyint] IKKE NULL, [TransactionBeginTime] [datetime] NOT NULL, [InsertUTCDate] [datetime] NOT NULL, [UpdateUTCDate] [datetime] IKKE NULL, BEGRÆNSNING [PK_SessionTran] PRIMÆR NØGLE KLUNDET ( [SessionID] ASC, [TransactionID] ASC) MED (PAD_INDEX =FRA, STATISTICS_NORECOMPUTE =FRA, IGNORE_DUP_KEY =FRA, ALLOW_ROW_LOCKS =TIL, ALLOW_PAGE_LOCKS =TIL) PÅ [PRIMÆR]) PÅ [PRIMARY]GOALTER TABLE [Session_Tran. 1 ) FOR [InsertUTCDate]GOALTER TABLE [srv].[Session Tran] TILFØJ BEGRÆNSNING [DF_SessionTran_UpdateUTCDate] DEFAULT (getutcdate()) FOR [UpdateUTCDate]GO

Her:

1) SessionID — sessions-id
2) Transaktions-ID — glemt transaktions-id
3) CountTranNotRequest — antallet af gange, en transaktion er blevet registreret som glemt
4) CountSessionNotRequest — antallet af gange en session uden aktive forespørgsler er blevet registreret og havde en glemt transaktion
5) TransactionBeginTime — dato og klokkeslæt for den glemte transaktions påbegyndelse
6) InsertUTCDate — dato og tidspunkt for oprettelse af post (UTC)
7) UpdateUTCDate — dato og klokkeslæt for indtastningsopdatering (UTC)

Dernæst opretter vi en tabel til at arkivere og sortere transaktionerne fra den første tabel ved at slette handlinger:

[expand title =”Kode “]

BRUG [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[KillSession]( [ID] [int] IDENTITY(1,1) NOT NULL, [session_id] [smallint] NOT NULL, [transaction_id] [bigint_id] ] NOT NULL, [login_time] [datetime] NOT NULL, [host_name] [nvarchar](128) NULL, [program_name] [nvarchar](128) NULL, [host_process_id] [int] NULL, [client_version] [int] NULL , [client_interface_name] [nvarchar](32) NULL, [security_id] [varbinary](85) NOT NULL, [login_name] [nvarchar](128) NOT NULL, [nt_domain] [nvarchar](128) NULL, [nt_user_name] [nvarchar](128) NULL, [status] [nvarchar](30) NOT NULL, [context_info] [varbinary](128) NULL, [cpu_time] [int] NOT NULL, [memory_usage] [int] NOT NULL, [ total_scheduled_time] [int] NOT NULL, [total_elapsed_time] [int] NOT NULL, [endpoint_id] [int] NOT NULL, [last_request_start_time] [datetime] NOT NULL, [sidste_request_end_time] [datetime] NULL, [reads NOT] [bigint] NULL, [skriver] [bigint] IKKE NULL, [logical_reads] [bigint] IKKE NULL, [is_user_process] [bit] NOT NULL, [text_size] [int] NOT NULL, [sprog] [nvarchar](128) NULL, [date_format] [nvarchar](3) NULL, [date_first] [smallint] IKKE NULL, [quoted_identifier] [bit] NOT NULL, [arithabort] [bit] IKKE NULL, [ansi_null_dflt_on] [bit] IKKE NULL, [ansi_defaults] [bit] IKKE NULL, [ansi_warnings] [bit] IKKE NULL, [ansi_padding] [bit] IKKE NULL, [ansi_nulls] [bit] IKKE NULL, [concat_null_yields_null] [bit] IKKE NULL, [transaction_isolation_level] [smallint] IKKE NULL, [lock_timeout] [int] IKKE NULL, [deadlock_priority] [int] IKKE NULL, [row_count] [bigint] IKKE NULL , [prev_error] [int] NOT NULL, [original_security_id] [varbinary](85) NOT NULL, [original_login_name] [nvarchar](128) NOT NULL, [last_successful_logon] [datetime] NULL, [last_unsuccessful_time]logon NULL [unsuccessful_logons] [bigint] NULL, [group_id] [int] IKKE NULL, [database_id] [smallint] IKKE NULL, [authenticating_database_id] [int] NULL, [open_transaction_count] [int] IKKE NULL, [mest_seneste_session_id] [int] , [tilslutningstid] [ datetime] NULL, [net_transport] [nvarchar](40) NULL, [protokoltype] [nvarchar](40) NULL, [protokolversion] [int] NULL, [encrypt_option] [nvarchar](40) NULL, [auth_scheme] [nvarchar ](40) NULL, [node_affinity] [smallint] NULL, [antal_reads] [int] NULL, [antal_writes] [int] NULL, [last_read] [datetime] NULL, [sidste_skrive] [datetime] NULL, [net_packet_size] [ int] NULL, [client_net_address] [nvarchar](48) NULL, [client_tcp_port] [int] NULL, [local_net_address] [nvarchar](48) NULL, [local_tcp_port] [int] NULL, [connection_id] [unik, identifikator] [parent_connection_id] [uniqueidentifier] NULL, [most_recent_sql_handle] [varbinary](64) NULL, [LastTSQL] [nvarchar](max) NULL, [transaction_begin_time] [datetime] NOT NULL, [CountTranNotRequest NOT] [tinyintRequest] [tinyintRequest] ] [tinyint] IKKE NULL, [InsertUTCDate] [datetime] NOT NULL, BEGRÆNSNING [PK_KillSession] PRIMÆR NØGLE KLUSTERET ( [ID] ASC) MED (PAD_INDEX =FRA, STATISTICS_NORECOMPUTE =FRA, IGNORE_DUP_KEY =ROW_LOCKOW_ =ROW ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]GOALTER TABEL [srv].[KillSession] TILFØJ BEGRÆNSNING [DF_KillSession_InsertUTCDate] STANDARD (getutcdate()>) FOR]GOPRUTCDateInsert 

[/udvid]

Her er alle felter taget fra systemrepræsentationerne 'sys.dm_exec_sessions' og 'sys.dm_exec_connections', og 'InsertUTCDate' angiver UTC-tidspunktet, hvor posten blev oprettet.

Lad os derefter implementere den lagrede procedure [srv].[AutoKillSessionTranBegin] som følger for at fuldføre de resterende trin:

[expand title =”Kode “]

BRUG [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[AutoKillSessionTranBegin] @minuteOld int, --alder på den udførte transaktion (T min.) @countIsNotRequests int --antallet af gange den er blevet placeret tabel (K)AS BEGIN SÆT ANTAL TIL; INDSTIL TRANSAKTIONS-ISOLERINGSNIVEAU LÆS UENGÆLDIGT; erklær @tbl tabel (SessionID int, TransactionID bigint, IsSessionNotRequest bit, TransactionBeginTime datetime); --hentning af information (transaktioner og deres session, der ikke har nogen anmodninger, dvs. transaktioner, der blev startet og glemt) indsæt i @tbl (SessionID, TransactionID, IsSessionNotRequest, TransactionBeginTime) vælg t.[session_id] som SessionID, t.[transaction_id] som TransactionID , case when exists(vælg top(1) 1 fra sys.dm_exec_requests som r hvor r.[session_id]=t.[session_id]) derefter 0 else 1 end as IsSessionNotRequest , (vælg top(1) ta.[transaction_begin_time ] fra sys.dm_tran_active_transactions as ta hvor ta.[transaction_id]=t.[transaction_id]) som TransactionBeginTime fra sys.dm_tran_session_transactions as t hvor t.[is_user_transaction]=1 og ikke eksisterer(vælg top(1) 1 fra sysc_remstsexe_ som r hvor r.[transaction_id]=t.[transaction_id]); --opfriskning af tabellen, der indeholder alle påbegyndte transaktioner uden anmodninger; flet srv.SessionTran som st ved hjælp af @tbl som t på st.[SessionID]=t.[SessionID] og st.[TransactionID]=t.[TransactionID] når de matches derefter opdater sæt [UpdateUTCDate] =getUTCDate() , [CountTranNotRequest] =st.[CountTranNotRequest]+1 , [CountSessionNotRequest] =tilfælde, når (t.[IsSessionNotRequest]=1) derefter (st.[CountSessionNotRequest]+1) else end , [TransactionBeginTime] =t.[TransactionBeginTime] når det ikke matches af målet, indsæt ( [SessionID] ,[TransactionBeginTime] ) værdier ( t.[SessionID] ,t.[TransactionID] ,t.[TransactionBeginTime] ) når den ikke matches af kilden, så slet; --liste over sessioner, der skal slettes (dem, der indeholder glemte transaktioner) erklærer @kills-tabel (SessionID int ); --детальная информация для архива declare @kills_copy table ( SessionID int, TransactionID bigint, CountTranNotRequest tinyint, CountSessionNotRequest tinyint, TransactionBeginTime datetime ) --indsamling af de sessioner, som vi havde brug for i det mindste at have dræbt en transaktion, som vi havde brug for at have mindst én transaktion. anmoder @countIsNotRequests gange -- og denne session blev markeret som at have ingen aktive anmodninger det samme antal gange indsat i @kills_copy ( SessionID, TransactionID, CountTranNotRequest, CountSessionNotRequest, TransactionBeginTime ) vælg SessionID, TransactionTime, CountTranNotSessionTransactionNot.CountSRequestRequestBegin hvor [CountTranNotRequest]>[email protected] og [CountSessionNotRequest]>[email protected] og [TransactionBeginTime]<=DateAdd(minut,[email protected],GetDate()); --arkivering af de data, vi skal slette (detaljer om de sessioner, der skal slettes, forbindelser og transaktioner) INSERT INTO [srv].[KillSession] ([session_id] ,[transaction_id] ,[login_time] ,[host_name] ,[program_name] ] ,[host_process_id] ,[client_version] ,[client_interface_name] ,[security_id] ,[login_name] ,[nt_domain],[nt_user_name] ,[status] ,[context_info] ,[cpu_time] ,[memory,_ustal] [total_elapsed_time] ,[endpoint_id] ,[last_request_start_time] ,[last_request_end_time] ,[reads] ,[writes] ,[logical_reads] ,[is_user_process] ,[text_size] ,[language_quote] ,[date_date] ,[date_date] ] ,[arithabort] ,[ansi_null_dflt_on] ,[ansi_defaults] ,[ansi_advarsler] ,[ansi_padding] ,[ansi_nulls] ,[concat_null_yields_null],[transaction_isolation_level] ,[lock_timeout] ,[deadlock_priority] ,[row_tæller] ,_ig-id, [forudgående_navn] ,_ig. last_successful_logon] ,[last_unsuccessful_logon] ,[unsuccessful_logons] ,[group_id] ,[database_id] ,[authenticating_database_id] ,[open_transaction_count] ,[mest_recent_session_id] ,[net_transport_protokol] ,,_cryption_protokol] ,[auth_scheme] ,[node_affinity] ,[antal_reads] ,[num_writes] ,[last_read] ,[last_write] ,[net_packet_size] ,[client_net_address] ,[client_tcp_port] ,[local_n e [login_tid] ,ES.[host_name] ,ES.[program_name] ,ES.[host_process_id] ,ES.[client_version] ,ES.[client_interface_name] ,ES.[security_id] ,ES.[login_name] ,ES.[nt_domain] ] ,ES.[nt_brugernavn] ,ES.[status] ,ES.[context_info] ,ES.[cpu_time] ,ES.[memory_usage] ,ES.[total_scheduled_time] ,ES.[total_elapsed_time] ,ES.[endpoint_id] , ES.[sidste_anmodning_starttid] ,ES.[sidste_anmodning_sluttid] ,ES.[læser] ,ES.[skriver] ,ES.[logisk_læsning] ,ES.[er_brugerproces ] ,ES.[text_size] ,ES.[sprog] ,ES.[date_format] ,ES.[date_first] ,ES.[quoted_identifier] ,ES.[arithabort] ,ES.[ansi_null_dflt_on] ,ES.[ansi_defaults] , ES.[ansi_warnings] ,ES.[ansi_padding] ,ES.[ansi_nulls] ,ES.[concat_null_yields_null] ,ES.[transaction_isolation_level] ,ES.[lock_timeout] ,ES.[deadlock_priority] ,ES.[row_count] [prev_error] ,ES.[original_security_id] ,ES.[original_login_name] ,ES.[last_successful_logon] ,ES.[last_unsuccessful_logon] ,ES.[unsuccessful_logons] ,ES.[group_id] ,ES.[ES.,databaseid] ] ,ES.[open_transaction_count] ,EC.[most_recent_session_id] ,EC.[connect_time] ,EC.[net_transport] ,EC.[protocol_type] ,EC.[protocol_version] ] ,EC.[encrypt_option] ,EC.[auth_scheme] ,EC.[node_affinity] ,EC.[num_reads] ,EC.[num_writes] ,EC.[last_read] ,EC.[last_write] ,EC.[net_packet_size] , EC.[client_net_address] ,EC.[client_tcp_port] ,EC.[local_net_address] ,EC.[local_tcp_port] ,EC.[connection_id] ,EC.[parent_connection_id] ,EC.[mest_recent_sql_handle] ,(se fra top) sys.dm_exec_sql_text(EC.[most_recent_sql_handle])) som [SidsteTSQL] ,kc.[TransactionBeginTime] ,kc.[CountTranNotRequest] ,kc.[CountSessionNotRequest] fra @kills_copy som kcdession on-readedsm_ joinES. .[SessionID]=ES.[session_id] indre join sys.dm_exec_connections EC with(readuncommitted) på EC.session_id =ES.session_id; --indsamlingssessioner indsæt i @kills ( SessionID ) vælg [SessionID] fra @kills_copy-gruppen ved [SessionID]; erklære @SessionID int; --deleting sessions while(exists(vælg top(1) 1 fra @kills)) start vælg top(1) @SessionID=[SessionID] fra @kills; BEGYND PRØV EXEC sp_executesql N'kill @SessionID', N'@SessionID INT', @SessionID; SLUT PRØV BEGYNDE FANG SLUT FANG Slet fra @kills hvor [SessionID][email protected]; end vælg st.[SessionID] ,st.[Transaktions-ID] ind i #tbl fra srv.SessionTran som st hvor st.[CountTranNotRequest]>=250 eller st.[CountSessionNotRequest]>=250 eller eksisterer(vælg top(1) 1 fra @kills_copy kc hvor kc.[SessionID]=st.[SessionsID]); --Sletning af de behandlede poster sammen med dem, der ikke kan fjernes og har været i tabellen for længe, ​​slet fra st fra #tbl som t indre join srv.SessionTran som st på t.[SessionID] =st.[SessionID] og t.[Transaktions-ID]=st.[Transaktions-ID]; drop-tabel #tbl;ENDGO

[/udvid]

Trin 7 i algoritmen implementeres gennem en af ​​disse to tællere – CountTranNotRequest eller CountSessionNotRequest – og når en værdi på 250.

Resultatet

I denne artikel har vi set på en implementering af en proces, der automatisk sletter glemte transaktioner.

Denne metode giver os mulighed for at automatisere processen for sletning af glemte transaktioner. Dette resulterer i at mindske eller standse fluktuationsvæksten i blokeringen produceret af sådanne transaktioner. Så DBMS-ydelsen er beskyttet mod handlinger, der kan resultere i glemte transaktioner.

Kilder:

» sys.dm_exec_requests
» sys.dm_tran_active_transactions
» sys.dm_tran_session_transactions
» sys.dm_exec_sql_text
» sys.dm_exec_sessions
_exec_sessions
_exe sys_>ILL


  1. Hvordan kan jeg ændre eksisterende kolonne som identitet i PostgreSQL 11.1

  2. Hvordan konfigurerer jeg HikariCP til postgresql?

  3. COT() Eksempler i SQL Server

  4. PHP PDO vs normal mysql_connect