sql >> Databáze >  >> RDS >> Access

TRANSACTION_MUTEX a přístup k více relacím

Nedávno jsem narazil na vysoký TRANSACTION_MUTEX akumulovaná doba čekání na klientském systému. Nepamatuji si případ, kdy bych viděl tento typ čekání jako blízko vrcholu seznamu „vysokých čekací“ a byl jsem zvědavý, jaké faktory mohou tento typ celkové čekací doby posunout.

Definice TRANSACTION_MUTEX v Books Online je, že "dochází během synchronizace přístupu k transakci pomocí více dávek." Tento typ funkcí nevykazuje mnoho oblastí v enginu SQL Serveru, takže moje šetření se zúžilo na následující technologie:

  • Zastaralý sp_getbindtoken a sp_bindsession systémové uložené procedury používané ke zpracování vázaných připojení
  • Distribuované transakce
  • MARS (Multiple Active Result Sets)

Mým cílem bylo otestovat každou technologii a zjistit, zda ovlivnila TRANSACTION_MUTEX typ čekání.

První test, který jsem provedl, použil zastaralý sp_getbindtoken a sp_bindsession uložené procedury. sp_getbindtoken vrátí identifikátor transakce, který pak může použít sp_bindsession pro svázání více relací na stejnou transakci.

Před každým testovacím scénářem jsem se ujistil, že jsem vymazal statistiku čekání své testovací instance SQL Server:

DBCC SQLPERF('waitstats', CLEAR);GO

Moje testovací instance SQL Server používala SQL Server 2012 SP1 Developer Edition (11.0.3000). Použil jsem vzorovou databázi kreditu, i když byste mohli použít jakýkoli jiný druh vzorové databáze, jako je AdventureWorks, pokud byste chtěli, protože schéma a distribuce dat přímo nesouvisí s předmětem tohoto článku a nebylo nutné k řízení TRANSACTION_MUTEX čekací doba.

sp_getbindtoken / sp_bindsession

V prvním okně relace SQL Server Management Studio jsem provedl následující kód pro zahájení transakce a výstup tokenu vazby pro zařazení do dalších plánovaných relací:

POUŽÍVEJTE kredit;ZAČNĚTE TRANSAKCI; DECLARE @out_token varchar(255); EXECUTE sp_getbindtoken @out_token OUTPUT; SELECT @out_token AS out_token;GO

To vrátilo @out_token z S/Z5_GOHLaGY<^i]S9LXZ-5---.fE--- . Ve dvou samostatných oknech dotazu SQL Server Management Studio jsem provedl následující kód pro připojení k existujícím relacím (přístup ke sdílené transakci):

USE Credit;GO EXEC sp_bindsession 'S/Z5_GOHLaGY<^i]S9LXZ-5---.fE---';

A když bylo okno první relace stále otevřené, spustil jsem následující smyčku, abych aktualizoval tabulku účtování poplatků s datem účtování rovným aktuálnímu datu a času, a pak jsem provedl stejnou logiku v dalších dvou oknech (tři aktivní relace v smyčka):

WHILE 1 =1 ZAČÁTE AKTUALIZOVAT dbo.charge SET charge_dt =SYSDATETIME();END

Po několika sekundách jsem každý provádějící dotaz zrušil. Ze tří relací byla pouze jedna schopna skutečně provádět aktualizace – i když další dvě relace byly aktivně připojeny ke stejné transakci. A když jsem se podíval na TRANSACTION_MUTEX wait type, vidím, že se skutečně zvýšil:

SELECT [wait_type], [waiting_tasks_count], [wait_time_ms], [max_wait_time_ms], [signal_wait_time_ms]FROM sys.dm_os_wait_statsWHERE wait_type ='TRANSACTION_MUTEX';

Výsledky tohoto konkrétního testu byly následující:

wait_type wait_tasks_count wait_time_ms max_wait_time_ms signal_wait_time_msTRANSACTION_MUTEX 2 181732 93899 0

Takže vidím, že tam byly dva čekající úkoly (dvě relace, které se současně pokoušely aktualizovat stejnou tabulku přes smyčku). Protože jsem neprovedl SET NOCOUNT ON , byl jsem schopen vidět, že pouze první provedené UPDATE smyčka prošla změnami. Zkoušel jsem tuto podobnou techniku ​​pomocí několika různých variant (například – čtyři celkové relace, tři čekání) – a TRANSACTION_MUTEX přírůstek vykazoval podobné chování. Také jsem viděl TRANSACTION_MUTEX akumulace při současné aktualizaci jiné tabulky pro každou relaci – takže úpravy proti stejnému objektu ve smyčce nebyly nutné k reprodukci TRANSACTION_MUTEX akumulace čekací doby.

Distribuované transakce

Můj další test zahrnoval zjištění, zda TRANSACTION_MUTEX čekací doba byla zvýšena pro distribuované transakce. Pro tento test jsem použil dvě instance SQL Server a propojený server připojený mezi nimi. MS DTC byl spuštěn a správně nakonfigurován a provedl jsem následující kód, který provedl místní DELETE a vzdálené DELETE přes propojený server a poté vrátil změny:

USE Credit;GO SET XACT_ABORT ON; -- Předpokládá, že služba MS DTC je dostupná, běžící, správně nakonfigurovanáZAČÁTEK DISTRIBUOVANÉ TRANSAKCE; DELETE [dbo].[charge] WHERE charge_no =1;DELETE [JOSEPHSACK-PC\AUGUSTUS].[Kredit].[dbo].[charge] WHERE charge_no =1; TRANSAKCE VRÁCENÍ;

TRANSACTION_MUTEX nevykazoval žádnou aktivitu na místním serveru:

wait_type wait_tasks_count wait_time_ms max_wait_time_ms signal_wait_time_msTRANSACTION_MUTEX 0 0 0 0

Počet čekajících úloh byl však na vzdáleném serveru zvýšen:

wait_type wait_tasks_count wait_time_ms max_wait_time_ms signal_wait_time_msTRANSACTION_MUTEX 1 0 0 0

Moje očekávání, že to uvidím, se tedy potvrdilo – vzhledem k tomu, že máme jednu distribuovanou transakci s více než jednou relací, která je nějakým způsobem zapojena do stejné transakce.

MARS (Multiple Active Result Sets)

A co použití Multiple Active Result Sets (MARS)? Očekávali bychom také, že uvidíme TRANSACTION_MUTEX akumulovat, když je spojeno s používáním MARS?

K tomu jsem použil následující kód konzolové aplikace C# testovaný z Microsoft Visual Studio proti mé instanci SQL Server 2012 a databázi Credit. Logika toho, co ve skutečnosti dělám, není příliš užitečná (vrací jeden řádek z každé tabulky), ale čtečky dat jsou na stejném připojení a atribut připojení MultipleActiveResultSets je nastaveno na true, takže stačilo ověřit, zda skutečně MARS dokáže řídit TRANSACTION_MUTEX akumulace také:

string ConnString =@"Server=.;Database=Credit;Trusted_Connection=True;MultipleActiveResultSets=true;";SqlConnection MARSCon =new SqlConnection(ConnString); MARSCon.Open(); SqlCommand MARSCmd1 =new SqlCommand("SELECT payment_no FROM dbo.payment;", MARSCon);SqlCommand MARSCmd2 =new SqlCommand("SELECT charge_no FROM dbo.charge;", MARSCon); SqlDataReader MARSReader1 =MARSCmd1.ExecuteReader();SqlDataReader MARSReader2 =MARSCmd2.ExecuteReader(); MARSReader1.Read();MARSReader2.Read(); Console.WriteLine("\t{0}", MARSReader1[0]);Console.WriteLine("\t{0}", MARSReader2[0]);

Po provedení tohoto kódu jsem viděl následující nahromadění pro TRANSACTION_MUTEX :

wait_type wait_tasks_count wait_time_ms max_wait_time_ms signal_wait_time_msTRANSACTION_MUTEX 8 2 0 0

Jak tedy vidíte, aktivita MARS (jakkoli triviálně implementovaná) způsobila nárůst v TRANSACTION_MUTEX akumulace typu čekání. A samotný atribut spojovacího řetězce to neřídí, skutečná implementace ano. Například jsem odstranil implementaci druhé čtečky a pouze jsem udržoval jednu čtečku s MultipleActiveResultSets=true a podle očekávání nedošlo k žádnému TRANSACTION_MUTEX akumulace čekací doby.

Závěr

Pokud vidíte vysokou hodnotu TRANSACTION_MUTEX čekání ve vašem prostředí, doufám, že vám tento příspěvek poskytne náhled do tří cest, které je třeba prozkoumat - abyste zjistili, odkud tato čekání pocházejí a zda jsou nebo nejsou nezbytná.


  1. Při pokusu o instalaci pg gem nelze najít hlavičku 'libpq-fe.h

  2. Užitečné tipy pro řešení běžných chyb v MySQL

  3. Hromadný import SQL z CSV

  4. Převeďte znaky latin1 v tabulce UTF8 na UTF8