sql >> Database >  >> RDS >> Database

De APPEND_ONLY_STORAGE_INSERT_POINT-vergrendeling

Als vervolg op mijn serie artikelen over vergrendelingen, ga ik deze keer de APPEND_ONLY_STORAGE_INSERT_POINT-vergrendeling bespreken en laten zien hoe dit een groot knelpunt kan zijn voor zware update-workloads waarbij een van beide vormen van snapshot-isolatie wordt gebruikt.

Ik raad je ten zeerste aan de eerste post in de serie voor deze te lezen, zodat je alle algemene achtergrondkennis over vergrendelingen hebt.

Wat is de APPEND_ONLY_STORAGE_INSERT_POINT-vergrendeling?

Om deze vergrendeling uit te leggen, moet ik een beetje uitleggen hoe snapshot-isolatie werkt.

Wanneer u een van de twee vormen van versiebeheer inschakelt, gebruikt SQL Server een mechanisme genaamd versiebeheer om pre-change versies te behouden van een record in de versiewinkel in tempdb. Dit gaat als volgt:

  • Er wordt vastgesteld dat een record op het punt staat te worden gewijzigd.
  • Het huidige record wordt gekopieerd naar het versiearchief.
  • Het record is gewijzigd.
  • Als de record nog geen 14-byte versie-tag had , wordt één toegevoegd aan het einde van het record. De tag bevat een tijdstempel (geen realtime) en een verwijzing naar de vorige versie van het record in de versieopslag.
  • Als de record al een versietag had, wordt deze bijgewerkt met de nieuwe tijdstempel en versieopslagaanwijzer.

Het tijdstempel voor versiebeheer voor de hele instantie wordt verhoogd wanneer een nieuwe instructie of batch begint, of een nieuwe versie van een record wordt gemaakt, in elke database waarin een van beide vormen van snapshot-isolatie is ingeschakeld. Deze tijdstempel wordt gebruikt om ervoor te zorgen dat een query de juiste versie van een record verwerkt.

Stelt u zich bijvoorbeeld een database voor die het lezen van vastgelegde snapshots had ingeschakeld, zodat elke instructie gegarandeerd de records ziet vanaf het moment dat de instructie is gestart. De versie-tijdstempel is ingesteld voor wanneer de instructie begon, dus elke record die hij tegenkomt met een hogere tijdstempel is de "verkeerde" versie, en dus moet de "juiste" versie, met een tijdstempel vóór de tijdstempel van de instructie, worden opgehaald uit de versie winkel. De mechanica van dit proces is niet relevant voor de doeleinden van dit bericht.

Dus, hoe worden de versies fysiek opgeslagen in het versiearchief? Het hele pre-change record, inclusief off-row kolommen, wordt gekopieerd naar het versiearchief, opgesplitst in brokken van 8.000 bytes, die indien nodig twee pagina's kunnen beslaan (bijv. 2.000 bytes aan het einde van een pagina en 6.000 bytes op het begin van de volgende). Deze opslag voor speciale doeleinden bestaat uit toevoegingseenheden die alleen kunnen worden toegevoegd en wordt alleen gebruikt voor bewerkingen voor versieopslag. Het wordt zo genoemd omdat nieuwe gegevens altijd pas direct na het einde van de laatst ingevoerde versie kunnen worden toegevoegd. Om de zoveel tijd wordt er een nieuwe toewijzingseenheid gemaakt, waardoor het opschonen van de reguliere versie van de winkel erg efficiënt is, omdat een onnodige toewijzingseenheid eenvoudig kan worden verwijderd. Nogmaals, de mechanica hiervan valt buiten het bestek van dit bericht.

En nu komen we bij de definitie van de vergrendeling:elke thread die een pre-change record naar het versiearchief moet kopiëren, moet weten waar het invoegpunt zich bevindt in de huidige toewijzingseenheid voor alleen toevoegen. Deze informatie wordt beschermd door de APPEND_ONLY_STORAGE_INSERT_POINT-vergrendeling.

Hoe wordt de vergrendeling een knelpunt?

Hier is het probleem:er is maar één acceptabele modus waarin de APPEND_ONLY_STORAGE_INSERT_POINT-vergrendeling kan worden verkregen:EX-modus (exclusief). En zoals je zult weten als je de introductiepost voor de serie leest, kan slechts één thread tegelijk de vergrendeling in de EX-modus vasthouden.

Al deze informatie samenbrengen:wanneer voor een of meer databases snapshot-isolatie is ingeschakeld, en er is een voldoende hoge gelijktijdige werklast van updates voor die databases, zullen er veel versies worden gegenereerd door de verschillende verbindingen, en deze vergrendeling wordt een een beetje een bottleneck, waarbij de bottleneck groter wordt naarmate de update-workload toeneemt als het om versiebeheer gaat.

De bottleneck laten zien

U kunt de bottleneck eenvoudig zelf reproduceren. Ik deed het als volgt:

  • Een tabel gemaakt met een aantal integer-kolommen met de naam cXXX, waarbij XXX een getal is en een geclusterde index op een int-identiteitskolom met de naam DocID
  • 100.000 records ingevoegd, met willekeurige waarden voor alle kolommen
  • Een script gemaakt met een oneindige lus om een ​​willekeurige DocID in het bereik van 1 tot 10.000 te selecteren, een willekeurige kolomnaam te selecteren en de kolomwaarde met 1 te verhogen (vandaar een versie maken)
  • Negen identieke scripts gemaakt, maar elk geselecteerd uit een ander sleutelbereik van 10.000 clusters
  • Stel DELAYED_DURABILITY in op FORCED om de wachttijden op WRITELOG te verminderen (toegegeven, u zou dit zelden doen, maar het helpt om het knelpunt voor demo-doeleinden te verergeren)

Ik heb toen alle tien scripts tegelijk uitgevoerd en de Access Methods:Index Searches/sec teller gemeten om bij te houden hoeveel updates er plaatsvonden. Ik kon Databases:Batch Requests/sec niet gebruiken omdat elk script maar één batch had (de oneindige lus), en ik wilde geen Transactions/sec gebruiken, omdat het zowel interne transacties zou kunnen tellen als degene die elke update inpakt.

Toen snapshot-isolatie niet was ingeschakeld, kreeg ik op mijn Windows 10-laptop met SQL Server 2019 ongeveer 80.000 updates per seconde via de tien verbindingen. Toen ik de instelling READ_COMMMITED_SNAPSHOT op AAN zette voor de database en de test opnieuw uitvoerde, daalde de doorvoer van de werklast tot ongeveer 60.000 updates per seconde (een daling van 25% in de doorvoer). Uit de wachtstatistieken bleek dat 85% van alle wachttijden LATCH_EX was en uit de statistieken van de vergrendeling:100% voor APPEND_ONLY_STORAGE_INSERT_POINT.

Houd er rekening mee dat ik het scenario heb opgezet om de bottleneck op zijn slechtst te laten zien. In een echte omgeving met een gemengde werklast is de algemeen aanvaarde richtlijn voor een doorvoerdaling bij gebruik van snapshot-isolatie 10-15%.

Samenvatting

Een ander potentieel gebied dat door dit knelpunt kan worden beïnvloed, zijn leesbare secundairen voor beschikbaarheidsgroepen. Als een database-replica is ingesteld om leesbaar te zijn, gebruiken alle query's ertegen automatisch snapshot-isolatie, en alle herhalingen van logboekrecords van de primaire zullen versies genereren. Met een updatewerkbelasting die hoog genoeg is afkomstig van de primaire en veel databases die zijn ingesteld om leesbaar te zijn, en omdat parallel opnieuw uitvoeren de norm is voor secundaire beschikbaarheidsgroepen, kan de APPEND_ONLY_STORAGE_INSERT_POINT-vergrendeling een knelpunt worden op een leesbare secundaire beschikbaarheidsgroep, wat zou kunnen leiden tot de secundair die achterloopt op de primaire. Ik heb dit niet getest, maar het is precies hetzelfde mechanisme dat ik hierboven heb beschreven, dus het lijkt waarschijnlijk. In dat geval is het mogelijk om parallel opnieuw uitvoeren uit te schakelen met traceringsvlag 3459, maar dit kan leiden tot een slechtere algehele doorvoer op de secundaire.

Het scenario van de beschikbaarheidsgroep opzij zetten, helaas is het niet gebruiken van snapshot-isolatie de enige manier om dit knelpunt volledig te vermijden, wat geen haalbare optie is als uw werklast afhankelijk is van de semantiek die wordt geboden door snapshot-isolatie, of u het nodig hebt om blokkeringsproblemen te verminderen (Omdat snapshot-isolatie betekent dat leesquery's geen gedeelde vergrendelingen verkrijgen die wijzigingsquery's blokkeren).

Bewerken:uit de onderstaande opmerkingen kunt u * de vergrendelings-knelpunt * verwijderen door ADR in SQL Server 2019 te gebruiken, maar dan zijn de prestaties veel slechter vanwege de ADR-overhead. Het scenario waarin de vergrendeling een knelpunt wordt vanwege de hoge update-workload is absoluut geen geldige use-case voor ADR.

  1. Hoe een UITLEG ANALYSE te begrijpen?

  2. waar 1=1 uitspraak

  3. Het mengen van expliciete en impliciete joins mislukt met Er is een item voor tabel ... maar er kan niet naar worden verwezen vanuit dit deel van de query

  4. Hoe associatieve arrays in Oracle Database te maken