sql >> Databáze >  >> RDS >> Sqlserver

Jak donutit souborový sběrač odpadu, aby dokončil svou práci s nejvyšší prioritou?

Bohužel v současné době neexistuje způsob, jak vynutit shromažďování odpadu (GC) dat filestreamu. Je zpracována asynchronní úlohou na pozadí, která se vyvolává pouze často a má omezený počet souborů, které může zpracovat při jednom vyvolání. Jiní lidé si na to již stěžovali a Microsoft slíbil, že tento problém vyřeší v budoucích verzích.

Jak již bylo řečeno, existuje několik věcí, které můžete proaktivně udělat, abyste zajistili, že všechny smazané soubory budou vhodné pro sběr odpadu. Soubor se automaticky nestane způsobilým pro shromažďování odpadu v okamžiku, kdy je smazán z databáze – musí být splněny určité dodatečné podmínky.

Podmínky závisí na modelu obnovy databáze, proto je důležité, abyste věděli, v jakém modelu obnovy se vaše databáze nachází. Všimněte si, že i když je model obnovy (jak je specifikován sys.databases) plný, ale neprovedli jste db/log backup od aktivace modelu úplné obnovy (nebo od vytvoření db) se databáze bude v mnoha ohledech chovat, jako by byla stále v jednoduchém modelu obnovy.

V rámci jednoduchého modelu obnovy stačí k tomu, aby byl soubor způsobilý k odstranění, aby aktuální LSN kontrolního bodu (LSN posledního kontrolního bodu) bylo větší než LSN operace odstranění, která soubor odstranila. Po smazání 40 000 řádků tedy můžete pouze vydat jediný příkaz CHECKPOINT a čekat.

Věci se komplikují, když je databáze v modelu obnovy „skutečně plná“. Pokud je tomu tak, pak kromě LSN kontrolního bodu musí být záložní LSN (LSN poslední zálohy protokolu) za LSN pro odstranění. Kromě toho GC funguje ve 2 fázích:při prvním průchodu pouze označí soubor ke smazání, ale fyzicky jej nesmaže. Teprve když GC zpracuje soubor podruhé, bude tento soubor fyzicky smazán z disku. Aby to bylo ještě zajímavější, první průchod GC "resetuje" vymazané LSN, takže druhý průchod může zpracovat soubor pouze tehdy, když LSN kontrolního bodu a záložní LSN jsou větší než LSN prvního průchodu GC.

Pokud chcete přesně vědět, co se v systému děje, můžete sledovat aktuální průběh GC pohledem na speciální interní tabulku „náhrobků“. Pokaždé, když je z databáze odstraněna hodnota filestreamu, je do této tabulky vložen náhrobek. Náhrobní kámen se odstraní až po smazání souboru z disku. Název tabulky náhrobek je sys.filestream_tombstone_, kde je nějaké číslo. Přesný název můžete získat pomocí následujícího dotazu:

select name from sys.internal_tables where name like '%tombstone%'

Vzhledem k tomu, že se jedná o interní tabulku, k jejímu dotazování se musíte přihlásit pomocí DAC (vyhrazené připojení správce).

Řekněme například, že jsem smazal řádek s jedinou hodnotou filestream. Nyní mohu zjistit stav náhrobku zadáním následujícího dotazu (z DAC):

select * from sys.filestream_tombstone_2073058421

První 3 pole označují LSN operace odstranění, ale nejdůležitější je sledovat stav. Po vydání zálohy protokolu + kontrolního bodu a jeho ponechání několik sekund běžet se znovu zeptám na tabulku náhrobků a dostanu:

Všimněte si, že se stav změnil (poslední 2 bity se změnily z 1 na 2), což znamená, že soubor byl zpracován prvním průchodem GC. LSN bylo navíc aktualizováno pomocí LSN prvního průchodu GC, takže aby bylo možné při druhém průchodu GC soubor nakonec smazat, musíme přenést LSN kontrolního bodu a záložní LSN nad nové LSN. Vydám další kontrolní bod + zálohu protokolu, počkám pár sekund a znovu se zeptám na tabulku náhrobků. Nyní je prázdný a soubor zmizel z disku.

Mějte na paměti, že existují další věci (např. replikace, jiné transakce, když je povoleno verzování), které mohou zabránit shromažďování odpadků u konkrétních souborů, ale ve většině případů jsou dvěma hlavními kontrolní bod a záloha protokolu.

Jejda, asi jsem zašel příliš hluboko do detailů, ale možná to nějakým způsobem pomůže pochopit chování GC.



  1. Jak sledovat chyby dotazů MySQL, časové limity a pokusy o přihlášení?

  2. Průvodce používáním pgBouncer pro PostgreSQL

  3. Vyhněte se zablokování pomocí nápovědy NOLOCK

  4. TODATETIMEOFFSET() Příklady v SQL Server