sql >> Databasteknik >  >> RDS >> Sqlserver

Automatisk radering av glömda transaktioner i MS SQL Server

Introduktion

Det är ofta fallet när en MS SQL Server-transaktion glöms bort av initiativtagaren. Det bästa exemplet skulle vara följande:ett skript exekveras i SSMS som via instruktionen ‘begin tran’ startar en transaktion och ett fel uppstår; "commit" eller "rollback" går dock inte igenom och exekveringsinitiatorn har lämnat denna fråga under lång tid. Som ett resultat uppstår fler och fler fluktuationer när det gäller att blockera de frågor som begär åtkomst till avstängda resurser (tabeller och serverresurser som RAM, CPU och input-output-systemet).

I den här artikeln ska vi titta på ett av sätten du kan automatisera processen för borttagning av glömda transaktioner.

Lösningen

Låt oss definiera en glömd transaktion som en aktiv (för närvarande genomförd) transaktion som under en tillräckligt lång tidsrymd T inte har några aktiva (för närvarande utförda) frågor.

Här är den allmänna algoritmen för att ta bort sådana transaktioner:

  1. Skapa en tabell för att lagra och analysera information om för närvarande glömda transaktioner samt en tabell för att sortera och arkivera de transaktioner som valts från den första tabellen genom raderingsåtgärder.
  2. Insamling av information (transaktioner och deras sessioner som inte har några frågor, d.v.s. de transaktioner som har utförts och glömts bort inom en angiven tidsperiod T.
  3. Uppdatera tabellen som innehåller alla för närvarande glömda transaktioner som vi fick i steg 1 (om en glömd transaktion har fått en aktiv fråga, kommer en sådan transaktion att tas bort från den här tabellen).
  4. Hämta de sessioner vi behöver döda (en session har minst en transaktion som placerades som glömd i tabellen från steg 1 K eller fler gånger och sessionen hade en saknad aktiv fråga lika många gånger).
  5. Arkivera data som vi ska radera (detaljer om sessioner, anslutningar och transaktioner som kommer att dödas).
  6. Tar bort de valda sessionerna.
  7. Ta bort de bearbetade posterna tillsammans med de som inte kan tas bort och som har funnits i tabellen från steg 1 för länge.

Nu ska vi se hur vi kan implementera den här algoritmen.
Först och främst måste vi skapa en tabell för att lagra och analysera informationen om alla för närvarande glömda transaktioner:

ANVÄND [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[SessionTran]( [SessionsID] [int] NOT NULL, [TransactionID] [bigint] NOT NULL, [CountTranNotRequest NOT] [tinyintRequest] ] [tinyint] NOT NULL, [TransactionBeginTime] [datetime] NOT NULL, [InsertUTCDate] [datetime] NOT NULL, [UpdateUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_SessionTran] PRIMÄRNYCKEL CLUSTERED ( [SessionsID] ASC, [TransactionID] ASC) MED (PAD_INDEX =AV, STATISTICS_NORECOMPUTE =AV, IGNORE_DUP_KEY =AV, ALLOW_ROW_LOCKS =PÅ, ALLOW_PAGE_LOCKS =PÅ) PÅ [PRIMÄR]) PÅ [PRIMARY]GOALTER TABLE [Session_Tran. 0)) FÖR [CountTranNotRequest]GOALTER TABLE [srv].[SessionTran] LÄGG TILL BEGRÄNSNING [DF_SessionTran_CountSessionNotRequest] DEFAULT ((0)) FÖR [CountSessionNotRequest]MÅLTABELL [srv].[SessionTran] ADD CONSTRAINT [SessionTran]_SEDUTSessionTrante(cD)DUTDFInd. ) FÖR [InsertUTCDate]MÅLTABELL [srv].[Session Tran] ADD CONSTRAINT [DF_SessionTran_UpdateUTCDate] DEFAULT (getutcdate()) FÖR [UpdateUTCDate]GO

Här:

1) SessionsID — sessionsidentifierare
2) TransaktionsID — glömt transaktionsidentifierare
3) CountTranNotRequest — antalet gånger en transaktion har registrerats som glömd
4) CountSessionNotRequest — antalet gånger en session utan aktiva förfrågningar har registrerats och haft en glömd transaktion
5) TransactionBeginTime — datum och tid för den glömda transaktionens initiering
6) InsertUTCDate — datum och tid för postens skapande (UTC)
7) UpdateUTCDate — datum och tid för inträdesuppdatering (UTC)

Därefter skapar vi en tabell för att arkivera och sortera transaktionerna från den första tabellen genom raderingsåtgärder:

[expand title =”Kod "]

ANVÄND [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, [last_request_end_time] [datetime] NULL, [reads NOT] [bitint] NULL, [skriver] [bigint] INTE NULL, [logical_reads] [bigint] INTE NULL, [är_användarprocess] [bit] NOT NULL, [text_size] [int] NOT NULL, [språk] [nvarchar](128) NULL, [date_format] [nvarchar](3) NULL, [date_first] [smallint] NOT NULL, [quoted_identifier] [bit] NOT NULL, [arithabort] [bit] NOT NULL, [ansi_null_dflt_on] [bit] NOT NULL, [ansi_defaults] [bit] NOT NULL, [ansi_warnings] [bit] NOT NULL, [ansi_padding] [bit] NOT NULL, [ansi_nulls] [bit] NOT NULL, [concat_null_yields_null] [bit] NOT NULL, [transaction_isolation_level] [smallint] NOT NULL, [lock_timeout] [int] NOT NULL, [deadlock_priority] [int] NOT NULL, [row_count] [bigint] NOT 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] NOT NULL, [database_id] [smallint] NOT NULL, [authenticating_database_id] [int] NULL, [open_transaction_count] [int] NOT NULL, [mest_senaste_session_id] [int] , [anslutningstid] [ datetime] NULL, [net_transport] [nvarchar](40) NULL, [protocol_type] [nvarchar](40) NULL, [protocol_version] [int] NULL, [encrypt_option] [nvarchar](40) NULL, [auth_scheme] [nvarchar ](40) NULL, [node_affinity] [smallint] NULL, [num_reads] [int] NULL, [num_writes] [int] NULL, [last_read] [datetime] NULL, [last_write] [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] [unique,identifier] [parent_connection_id] [uniqueidentifier] NULL, [most_recent_sql_handle] [varbinary](64) NULL, [LastTSQL] [nvarchar](max) NULL, [transaction_begin_time] [datetime] NOT NULL, [CountTranNotRequest NOT] [tinyintquest] [tinyintquest] ] [tinyint] NOT NULL, [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_KillSession] PRIMÄRNYCKEL KLUSTERAD ( [ID] ASC) MED (PAD_INDEX =AV, STATISTICS_NORECOMPUTE =AV, IGNORE_DUP_KEY =AV, IGNORE_DUP_KEY =AV, LOCKOW_ ROW PÅ, ALLOW_PAGE_LOCKS =PÅ) PÅ [PRIMÄR]) PÅ [PRIMÄR] TEXTIMAGE_ON [PRIMÄR]MÅLTABELL [srv].[KillSession] LÄGG TILL BEGRÄNSNING [DF_KillSession_InsertUTCDate] DEFAULT (getutcdate()>) FÖR [GOPreUTCDate] 

[/expand]

Här är alla fält hämtade från systemrepresentationerna 'sys.dm_exec_sessions' och 'sys.dm_exec_connections', och 'InsertUTCDate' anger UTC-tiden då posten skapades.

Sedan, för att slutföra de återstående stegen, låt oss implementera den lagrade proceduren [srv].[AutoKillSessionTranBegin] enligt följande:

[expand title =”Kod "]

ANVÄND [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[AutoKillSessionTranBegin] @minuteOld int, --ålder på den utförda transaktionen (T min.) @countIsNotRequests int --antalet gånger den har placerats tabell (K)ÅR BÖRJAN STÄLLA IN NOCOUNT PÅ; STÄLL IN TRANSAKTIONSISOLERINGSNIVÅ LÄS OENGAGERAD; deklarera @tbl-tabell (SessionsID int, TransactionID bigint, IsSessionNotRequest bit, TransactionBeginTime datetime); --hämta information (transaktioner och deras session som inte har några förfrågningar, dvs transaktioner som initierades och glömdes) infoga i @tbl ( SessionID, TransactionID, IsSessionNotRequest, TransactionBeginTime ) välj t.[session_id] som SessionID , t.[transaction_id] som TransactionID , case when exists(välj top(1) 1 från sys.dm_exec_requests som r där r.[session_id]=t.[session_id]) sedan 0 else 1 slut som IsSessionNotRequest , (välj top(1) ta.[transaction_begin_time ] från sys.dm_tran_active_transactions som ta där ta.[transaction_id]=t.[transaction_id]) som TransactionBeginTime från sys.dm_tran_session_transactions som t där t.[is_user_transaction]=1 och inte existerar(välj top(1) 1 från sys.dmst_exe som r där r.[transaktions-id]=t.[transaktions-id]); --uppdatera tabellen som innehåller alla initierade transaktioner utan förfrågningar; slå samman srv.SessionTran som st med @tbl som t på st.[SessionsID]=t.[SessionsID] och st.[TransaktionsID]=t.[TransaktionsID] när de matchas sedan uppdatera set [UpdateUTCDate] =getUTCDate() , [CountTranNotRequest] =st.[CountTranNotRequest]+1 , [CountSessionNotRequest] =fall när (t.[IsSessionNotRequest]=1) sedan (st.[CountSessionNotRequest]+1) annars 0 end , [TransactionBeginTime] =t.[TransactionBeginTime] när den inte matchas av målet infogar du ( [SessionID] ,[TransactionBeginTime] ) värden ( t.[SessionsID] ,t.[TransactionID] ,t.[TransactionBeginTime] ) när den inte matchas av källan, ta bort; --lista över sessioner som måste raderas (de som innehåller glömda transaktioner) deklarerar @kills-tabell (SessionID int ); --детальная информация для архива declare @kills_copy table ( SessionID int, TransactionID bigint, CountTranNotRequest tinyint, CountSessionNotRequest tinyint, TransactionBeginTime datetime ) --samlar in de sessioner som vi behövde för att inte ha minst en session som vi behövde döda begär @countIsNotRequests gånger -- och den här sessionen markerades som att den inte hade några aktiva förfrågningar samma antal gånger infoga i @kills_copy ( SessionID, TransactionID, CountTranNotRequest, CountSessionNotRequest, TransactionBeginTime ) välj SessionID, TransactionID, CountTranNotSessionRequest, TransactionNotRequerBegin där [CountTranNotRequest]>[email protected] och [CountSessionNotRequest]>[email protected] och [TransactionBeginTime]<=DateAdd(minute,[email protected],GetDate()); --arkivering av data vi behöver radera (detaljer om sessionerna som ska raderas, anslutningar och transaktioner) INFOGA 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] ,[minne,_användningstid] [total_elapsed_time] ,[endpoint_id] ,[last_request_start_time] ,[last_request_end_time] ,[reads] ,[writes] ,[logical_reads] ,[is_user_process] ,[text_size] ,[language_quoted] ,[date_date] ,[date_date] ] ,[arithabort] ,[ansi_null_dflt_on] ,[ansi_defaults] ,[ansi_warnings] ,[ansi_padding] ,[ansi_nulls] ,[concat_null_yields_null],[transaction_isolation_level] ,[lock_timeout] ,[deadlock_priority] ,[rad_nulls] ,[rad_räkneverk] ,_iginalnamn] ,_iginalnummer] ,_ig. last_successful_logon] ,[last_unsuccessful_logon] ,[unsuccessful_logons] ,[group_id] ,[databas_id] ,[authenticating_database_id] ,[open_transaction_count] ,[most_recent_session_id] ,[connect_time_protocol] ,[krypteringsprotokoll] ,[auth_scheme] ,[node_affinity] ,[num_reads] ,[num_writes] ,[last_read] ,[last_write] ,[net_packet_size] ,[client_net_address] ,[client_tcp_port] ,[local_n et_address],[local_tcp_port],[connection_id] ,[parent_connection_id] ,[most_recent_sql_handle] ,[LastTSQL],[transaction_begin_time],[CountTranNotRequest] ,[CountSessionNotRequest] ,session_ID,ES.[session-ID,ES.[sessions-ID]]) [login_time] ,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_user_name] ,ES.[status] ,ES.[context_info] ,ES.[cpu_time] ,ES.[memory_usage] ,ES.[total_scheduled_time] ,ES.[total_elapsed_time] ,ES.[endpoint_id] , ES.[last_request_starttime] ,ES.[last_request_end_time] ,ES.[reads] ,ES.[writes] ,ES.[logical_reads] ,ES.[is_user_process ] ,ES.[text_size] ,ES.[språk] ,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.[databas_id] ] ,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.[most_recent_sql_handle] ,(se text from top] ,(se sys.dm_exec_sql_text(EC.[most_recent_sql_handle])) som [LastTSQL] ,kc.[TransactionBeginTime] ,kc.[CountTranNotRequest] ,kc.[CountSessionNotRequest] från @kills_copy som kcdsession ondsession inre anslutning sycmitts) exe .[SessionID]=ES.[session_id] inner join sys.dm_exec_connections EC with(readuncommitted) på EC.session_id =ES.session_id; --gathering sessions insert into @kills ( SessionID ) välj [SessionID] från @kills_copy group by [SessionID]; deklarera @SessionID int; --deleting sessions while(exists(välj topp(1) 1 från @kills)) start select top(1) @SessionID=[SessionsID] från @kills; BÖRJA PRÖVA EXEC sp_executesql N'kill @SessionID', N'@SessionID INT', @SessionID; SLUT FÖRSÖK BÖRJA FÅNGTA SLUT FÅNGTA radera från @kills där [SessionsID][email protected]; slut välj st.[SessionID] ,st.[Transaktions-ID] till #tbl från srv.SessionTran som st där st.[CountTranNotRequest]>=250 eller st.[CountSessionNotRequest]>=250 eller existerar(välj topp(1) 1 från @kills_copy kc där kc.[SessionsID]=st.[SessionsID]); --Ta bort de behandlade posterna tillsammans med de som inte kan tas bort och som har funnits i tabellen för länge radera från st från #tbl som t inner join srv.SessionTran as st on t.[SessionID] =st.[SessionID] och t.[Transaktions-ID]=st.[Transaktions-ID]; släpptabell #tbl;ENDGO

[/expand]

Steg 7 i algoritmen implementeras genom att en av dessa två räknare – CountTranNotRequest eller CountSessionNotRequest – når värdet 250.

Resultatet

I den här artikeln har vi tittat på en implementering av en process som automatiskt tar bort glömda transaktioner.

Denna metod tillåter oss att automatisera bortglömda transaktioner. Detta resulterar i att fluktuationstillväxten i blockeringen som produceras av sådana transaktioner minskar eller stoppas. Så DBMS-prestandan är skyddad från de åtgärder som kan resultera i glömda transaktioner.

Källor:

» 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. ODP.NET-anslutningspoolning:Hur man avgör om en anslutning har använts

  2. PL/SQL ORA-01422:exakt hämtning returnerar fler än begärt antal rader

  3. Varför får jag den här SQLSyntaxErrorException:ORA-00933:SQL-kommandot avslutades inte korrekt när jag försöker utföra den här JDBC-frågan?

  4. Hur man läser och återställer AUTO_INCREMENT i MySQL