De ce commit-ul SQL sincron așteaptă călătoria dus-întors prin VPN
Commit-ul sincron dintr-un grup de disponibilitate include întărirea jurnalului remote. Măsurați acea cale înainte de a da vina pe lățimea de bandă sau de a schimba modul.
Latența scrierii a sărit după ce o replică a fost mutată pe al doilea sit, iar tunelul este cea mai nouă componentă, așa că el primește vina. Tunelul poate fi nevinovat: într-un grup de disponibilitate cu commit sincron, primara nu poate confirma un commit până când nu se încheie o scriere remote în jurnal, așa că fiecare tranzacție plătește o călătorie dus-întors, indiferent de câți megabiți poate duce legătura. Debitul măsoară biți pe secundă, latența măsoară cât durează un schimb, iar un commit are nevoie doar de un schimb mic ca să se termine. Un singur număr închide discuția: durata commit-ului unei tranzacții mici, măsurată în baza de date de disponibilitate și apoi din nou față de un tabel local pe aceeași instanță.
Ce așteaptă de fapt primara
Sub commit sincron, primara ține confirmarea commit-ului până când partenerul confirmă că înregistrările sale din jurnal sunt întărite. Întărit înseamnă scris durabil în jurnalul de tranzacții al secundarei, nu reexecutat în paginile ei de date. Redo poate rămâne în urmă cu minute fără a adăuga o singură milisecundă la commit-ul primarei.
Documentația Microsoft despre modurile de disponibilitate explică acel handshake și descrie ce face platforma când un partener cade. O replică marcată ca sincronă este o regulă despre așteptare, nu o promisiune permanentă că există o copie remote sănătoasă pentru fiecare commit. Calea deconectată este definită separat, și nu este pur și simplu faptul că commit-ul eșuează.
Deci așteptarea pe care o vedeți este o sumă: transportul jurnalului, planificarea pe ambele gazde și scrierea în stocarea remote. O secundară cu volum de jurnal saturat adaugă timp pe care niciun test de viteză nu îl va arăta. Acel disc este rar măsurat când reclamația numește VPN-ul.
Lățimea de bandă nu este întârziere dus-întors
Un test de viteză inundă calea pentru scurt timp și raportează o rată. Un commit cere ceva mai îngust: cât durează ca un mesaj mic să ajungă pe cealaltă parte, să fie persistat și să revină. Lungimea căii, cozile și pierderea de pachete stabilesc acel număr, și niciunul nu se îmbunătățește când furnizorul ridică plafonul.
Un tunel «rapid» poate deci adăuga o penalizare vizibilă unei încărcări grele pe scriere, construită din multe tranzacții mici secvențiale. Același total de biți împărțit la o mie de commit-uri plătește călătoria dus-întors de o mie de ori; un transfer în bloc o plătește o dată.
Cereți proprietarului rețelei întârzierea și pierderea măsurate pe ruta replicii înseși sub o încărcare reprezentativă. Un ping de pe un laptop de birou către gateway-ul VPN, sau un test de viteză către un nod apropiat, nu atribuie aproape nimic rutei pe care jurnalul chiar călătorește. Faceți fereastra de măsurare să se suprapună cu orele în care scrierea este lentă.
Citiți starea replicii înainte de a schimba ceva
Începeți cu ce raportează instanțele despre ele însele, pentru că cele două părți pot să nu fie de acord cu privire la cât de sănătos este parteneriatul și o medie de panou ascunde care coadă se mișcă. Interogările de mai jos răspund la întrebări diferite: una citește starea replicării pe baze de date, cealaltă citește cum este configurată fiecare replică. Rulați-le pe amândouă înainte de a atinge un mod.
SELECT ag.name AS ag_name, drs.database_id, drs.synchronization_state_desc,
drs.log_send_queue_size, drs.redo_queue_size, drs.secondary_lag_seconds
FROM sys.dm_hadr_database_replica_states AS drs
JOIN sys.availability_groups AS ag ON ag.group_id = drs.group_id;
SELECT ar.replica_server_name, ar.availability_mode_desc, ar.failover_mode_desc
FROM sys.availability_replicas AS ar;
Primul rezultat separă transportul jurnalului de redo. log_send_queue_size crescând în timp ce redo_queue_size rămâne plat înseamnă că jurnalul nu a ajuns; inversul înseamnă că a ajuns și că reluarea rămâne în urmă. Doar primul caz stă pe calea commit-ului.
Al doilea rezultat confirmă care replici sunt cu adevărat configurate așa cum presupuneți, pentru că un mod schimbat în timpul unui incident anterior tinde să rămână schimbat și nedocumentat. Citiți rândul care vă interesează în locul valorii implicite a grupului: availability_mode_desc și failover_mode_desc sunt pe replică. secondary_lag_seconds există doar pe SQL Server 2016 și mai nou, așa că o versiune mai veche vă lasă doar cu coloanele cozii de trimitere și ale redo-ului.
Apoi măsurați o scriere reprezentativă în loc să vă bazați pe o medie de panou. Rulați blocul de mai jos în baza de date de disponibilitate, apoi rulați-l din nou față de aceeași formă de tabel într-o bază de date din afara grupului, pe aceeași instanță. Diferența dintre cele două durate este un preț aproximativ al jurnalului remote, și într-o discuție cu echipa de rețea rezistă mult mai bine decât un grafic. După aceea schimbați o variabilă pe rând, altfel diferența nu mai înseamnă nimic.
IF OBJECT_ID('dbo.CommitProbe') IS NULL
CREATE TABLE dbo.CommitProbe (probe_id int PRIMARY KEY, touched_at datetime2(3));
IF NOT EXISTS (SELECT 1 FROM dbo.CommitProbe WHERE probe_id = 1)
INSERT INTO dbo.CommitProbe (probe_id) VALUES (1);
SET STATISTICS TIME ON;
BEGIN TRANSACTION;
UPDATE dbo.CommitProbe SET touched_at = SYSUTCDATETIME() WHERE probe_id = 1;
COMMIT TRANSACTION;
SET STATISTICS TIME OFF;
Ce cumpără commit-ul asincron și cât costă
Cu commit asincron, primara nu mai așteaptă confirmarea întăririi remote, așa că călătoria dus-întors părăsește calea commit-ului. Latența commit-ului scade și secundara este liberă să rămână în urmă cu o cantitate pe care nimeni nu o controlează. Este o corecție reală pentru așteptare și o schimbare reală a promisiunii.
Prețul este o decizie despre punctul de recuperare. Dacă primara moare înainte ca jurnalul ei să ajungă la o țintă de failover pe care chiar o puteți folosi, mutarea serviciului pe copia asincronă aruncă tranzacții pe care aplicația le raportase deja ca fiind confirmate. Nicio casetă de configurare nu o prezintă așa, pentru că este o întrebare de afaceri despre pierderea acceptabilă, nu o setare de performanță. Scrieți fereastra de pierdere tolerată înainte de incident, nu în timpul lui.
Stabiliți modul împreună cu proprietarul datelor, în scris, împreună cu procedura de failover pentru cazul în care ținta preferată nu este disponibilă. Sincron într-un document de proiectare nu este un manual operațional, iar asincron nu este o licență de a opri monitorizarea cozilor.
Alegeți o corecție pe care o puteți apăra mai târziu
Există patru opțiuni oneste. Tăiați călătoriile dus-întors ale commit-ului care pot fi evitate acolo unde semantica aplicației permite gruparea; reparați un blocaj de transport sau de stocare pe care l-ați măsurat, ceea ce poate însemna un volum de jurnal mai rapid pe secundară în loc de o țeavă mai mare; apropiați replica astfel încât călătoria dus-întors să scadă; sau relaxați politica de protecție și acceptați o fereastră de pierdere mai largă. Fiecare cumpără latență cheltuind altceva, iar a patra cheltuiește durabilitate. Numiți cheltuiala înainte de a alege.
Decideți cu ținta de latență a încărcării și cerința ei de durabilitate în față în același timp, pentru că optimizarea uneia o cheltuiește în liniște pe cealaltă. Apoi rulați din nou aceeași tranzacție pe care ați măsurat-o înainte de schimbare. O corecție care nu poate mișca acel număr este o presupunere cu un tichet de schimbare.
Păstrați citirile de dinainte și de după în înregistrarea schimbării. Altfel următoarea persoană care vede scrieri lente repetă investigația de la început și începe din nou să dea vina pe tunel.