Hantera filutrymme för databaser i Azure SQL Database

gäller för:Azure SQL Database

I den här artikeln beskrivs olika typer av lagringsutrymme för databaser i Azure SQL Database. Du kan ibland behöva hantera det tilldelade filutrymmet uttryckligen. Den här artikeln innehåller stegen för att göra detta.

Överblick

Vissa arbetsbelastningsmönster kan göra att det utrymme som tilldelas datafiler blir större än det använda utrymmet. Detta tillstånd uppstår när det använda utrymmet ökar på grund av datatillväxt, men du senare raderar eller komprimerar data. Det tilldelade men oanvända utrymmet återtas inte automatiskt eftersom återvinning är resurskrävande och skulle bromsa framtida filtillväxt.

Du kan behöva krympa datafiler och återta oanvänt utrymme i följande scenarier:

  • Att möjliggöra datatillväxt för databaser i en elastisk pool när ett stort allokerat utrymme för vissa databaser i poolen gör att poolen närmar sig sin maximala storlek.
  • För att möjliggöra en minskning av den maximala storleken på en enskild databas eller elastisk pool.
  • För att ändra databasen eller en elastisk pool till en tier med en lägre maximal storleksgräns.
  • För att minska lagringskostnader vid användning av Hyperscale-servicenivån.

Försiktighet

Betrakta inte krympningsåtgärder som en vanlig underhållsåtgärd. Data och loggfiler som växer på grund av regelbundna återkommande affärsåtgärder kräver inte krympningsåtgärder.

Övervaka filutrymmesanvändning

Azure Resource Manager (ARM) API:er, inklusive PowerShell get-metrics, returnerar det använda och tilldelade utrymmet för databaser och elastiska pooler.

Följande systemvyer återger också storleken på använt och tilldelat utrymme för databaser och elastiska pooler:

Förstå typer av lagringsutrymme för en databas

Det är viktigt att förstå följande lagringsutrymmeskvantiteter för att hantera filutrymmet i en databas.

Databaskvantitet Definition Kommentarer
Datautrymme som används Mängden utrymme som används för att lagra data. I allmänhet ökar utrymmet som används (minskar) vid infogningar (borttagningar). I vissa fall ändras inte det utrymme som används vid infogningar eller borttagningar beroende på mängden och mönstret för data som ingår i åtgärden och eventuell fragmentering. Om du till exempel tar bort en rad från varje datasida minskar inte nödvändigtvis det utrymme som används.
Allokerat datautrymme Mängden lagringsutrymme som datafiler tar. Mängden tilldelat utrymme växer automatiskt, men minskar aldrig automatiskt efter raderingar. Detta beteende säkerställer att framtida insättningar går snabbare eftersom utrymme inte behöver omallokeras.
Allokerat datautrymme men oanvänt Skillnaden mellan mängden allokerat datautrymme och det datautrymme som används. Den här kvantiteten representerar den maximala mängden ledigt utrymme som kan frigöras genom krympande databasdatafiler.
Data maxstorlek Den maximala mängden utrymme som kan användas för att lagra data. Mängden allokerat datautrymme kan inte bli större än den maximala datastorleken.

Följande diagram illustrerar relationen mellan de olika typerna av lagringsutrymme för en databas.

diagram som visar storleken på olika databasutrymmesbegrepp i databaskvantitetstabellen.

Fråga en enskild databas om information om filutrymme

Använd följande fråga på sys.database_files för att returnera mängden allokerat databasfilutrymme och mängden oanvänt utrymme som allokerats.

-- Connect to a user database
SELECT file_id,
       type_desc,
       CAST (FILEPROPERTY(name, 'SpaceUsed') AS DECIMAL (19, 4)) * 8 / 1024. AS space_used_mb,
       CAST (size / 128.0 - CAST (FILEPROPERTY(name, 'SpaceUsed') AS INT) / 128.0 AS DECIMAL (19, 4)) AS space_unused_mb,
       CAST (size AS DECIMAL (19, 4)) * 8 / 1024. AS space_allocated_mb,
       CAST (max_size AS DECIMAL (19, 4)) * 8 / 1024. AS max_size_mb
FROM sys.database_files;

Förstå typer av lagringsutrymme för en elastisk pool

Att förstå följande lagringsutrymmeskvantiteter är viktigt för att hantera filutrymmet i en elastisk pool.

Elastiskt poolantal Definition Kommentarer
Datautrymme som används Sammanfattningen av datautrymme som används av alla databaser i den elastiska poolen.
Allokerat datautrymme Summan av lagringsutrymme som tas upp av datafiler i alla databaser i den elastiska poolen.
Allokerat datautrymme men oanvänt Skillnaden mellan mängden allokerat datautrymme och det datautrymme som används av alla databaser i den elastiska poolen. Den här kvantiteten representerar den maximala mängden utrymme som allokerats för den elastiska poolen som kan frigöras genom krympande databasdatafiler.
Data maxstorlek Den maximala mängden datautrymme som en elastisk pool använder för alla sina databaser. Utrymmet som har allokerats för den elastiska poolen bör inte överstiga den elastiska poolens maximistorlek. Om detta tillstånd uppstår kan de tilldelade men oanvända datafilerna återtas genom att krympa datafilerna.

Felmeddelandet "Den elastiska poolen har nått sin lagringsgräns" indikerar att databasobjekten förbrukar tillräckligt med utrymme för att uppfylla den maximala lagringsgränsen för den elastiska poolen. Överväg att öka lagringsgränsen, eller frigör datautrymme som beskrivs i Reclaim unused allocated space.

Fråga efter information om lagringsutrymme i en elastisk pool

Använd följande frågor för att bestämma lagringsutrymmesmängder för en elastisk pool.

Elastiskt pooldatautrymme som används

Använd följande exempelfråga för att returnera mängden elastiskt pooldatautrymme som används. Ändra namnparametern för den elastiska poolen så att det matchar namnet på din pool.

-- Connect to master
SELECT TOP (1) avg_storage_percent / 100.0 * elastic_pool_storage_limit_mb AS elastic_pool_space_used_mb,
               avg_allocated_storage_percent / 100.0 * elastic_pool_storage_limit_mb AS elastic_pool_space_allocated_mb,
               elastic_pool_storage_limit_mb AS elastic_pool_maximum_size_mb
FROM sys.elastic_pool_resource_stats
WHERE elastic_pool_name = 'ep1'
ORDER BY end_time DESC;

Frigöra oanvänt allokerat utrymme

Viktig

Krympningsoperationer förbrukar resurser och kan påverka databasens prestanda medan de pågår. När det är möjligt, kör krympning under perioder med låg användning.

Komprimera datafiler

Eftersom förminskning av datafiler kan påverka databasens prestanda, krymper inte Azure SQL Database automatiskt datafilerna. Om det behövs kan du krympa datafiler vid en tidpunkt du själv väljer. Gör inte krympning till en regelbundet schemalagd åtgärd. Överväg istället att använda den först efter en stor minskning av den använda platsförbrukningen.

Tips

Slösa inte beräkningsresurser och tid på att krympa datafiler om den vanliga applikationsarbetsbelastningen gör att filerna återigen växer till samma tilldelade storlek.

För att krympa filer, använd antingen DBCC SHRINKDATABASE T-SQL-kommandon DBCC SHRINKFILE :

  • DBCC SHRINKDATABASE krymper all data och loggfiler i en databas med ett enda kommando. Kommandot krymper en datafil i taget, vilket kan ta lång tid för större databaser. Det också krymper loggfilen, vilket vanligtvis är onödigt eftersom Azure SQL Database krymper loggfilerna automatiskt efter behov.
  • DBCC SHRINKFILE-kommandot stöder mer avancerade scenarier:
    • Den kan rikta in sig på enskilda filer efter behov i stället för att krympa alla filer i databasen.
    • Varje DBCC SHRINKFILE kommando kan köras parallellt med andra DBCC SHRINKFILE kommandon för att minska den totala krymptiden, på bekostnad av högre resursanvändning och en större risk att tillfälligt blockera användarfrågor och samtidiga DBCC SHRINKFILE kommandon.
    • Om svansen på filen inte innehåller data kan du minska den tilldelade filstorleken snabbare genom att specificera argumentet TRUNCATEONLY . TRUNCATEONLY Det kräver inte datarörelse inom filen, men minskar inte heller den tilldelade storleken lika mycket.
  • Mer information om dessa krympningskommandon finns i DBCC SHRINKDATABASE och DBCC SHRINKFILE.

Kör följande exempel medan du är ansluten till målanvändardatabasen, inte databasen master .

Så här använder du DBCC SHRINKDATABASE för att krympa alla data och loggfiler i en viss databas:

DBCC SHRINKDATABASE (N'database_name');

En databas kan ha en eller flera datafiler, som skapas automatiskt när data växer. För att bestämma fillayouten i din databas, inklusive den använda och tilldelade storleken på varje fil, sök katalogvyn sys.database_files med följande exempelskript:

-- Review file properties, including the file_id and name values to use in shrink commands
SELECT file_id,
       name,
       CAST (FILEPROPERTY(name, 'SpaceUsed') AS BIGINT) * 8 / 1024. AS space_used_mb,
       CAST (size AS BIGINT) * 8 / 1024. AS space_allocated_mb,
       CAST (max_size AS BIGINT) * 8 / 1024. AS max_file_size_mb
FROM sys.database_files
WHERE type_desc IN ('ROWS', 'LOG');

För att krympa en enskild fil, använd kommandot DBCC SHRINKFILE , till exempel:

-- Shrink database data file named 'data_0` by removing all unused at the end of the file, if any.
DBCC SHRINKFILE ('data_0', TRUNCATEONLY);

Krymp transaktionsloggfil

Till skillnad från datafiler krymper Azure SQL Database automatiskt transaktionsloggfilen för att undvika överdriven utrymmesanvändning som kan leda till out-of-space-fel. I de flesta fall behöver du inte krympa transaktionsloggfilen.

I Premium- och Business Critical-tjänstenivåerna, om transaktionsloggen blir stor, kan den bidra avsevärt till den lokala lagringsförbrukningen mot den maximala lokala lagringsgränsen . Om lokal lagringsförbrukning är nära gränsen kan du välja att krympa transaktionsloggen med kommandot DBCC SHRINKFILE som visas i följande exempel. Detta frigör lokal lagring så snart kommandot har slutförts, utan att vänta på den periodiska automatiska krympningsåtgärden.

Kör följande exempel medan du är ansluten till målanvändardatabasen, inte databasen master .

-- Shrink the database log file (always file_id 2), by removing all unused space at the end of the file, if any.
DBCC SHRINKFILE (2, TRUNCATEONLY);

Krymp automatiskt

Som ett alternativ till att krympa datafiler manuellt kan automatisk krympning aktiveras för en databas. Automatisk krympning kan dock vara mindre effektivt när det gäller att frigöra filutrymme än DBCC SHRINKDATABASE och DBCC SHRINKFILE.

Som standard inaktiveras automatisk krympning, vilket rekommenderas för de flesta databaser. Om det blir nödvändigt att aktivera automatisk förminskning rekommenderas det att inaktivera det när målen för utrymmeshantering är uppnått, istället för att ha det permanent aktiverat. Mer information finns i Överväganden för AUTO_SHRINK.

Till exempel kan auto-krympning vara hjälpsamt om en elastisk pool innehåller många databaser som kontinuerligt upplever betydande tillväxt och minskning av det använda utrymmet, vilket gör att poolen närmar sig sin maximala storleksgräns. Det här scenariot är inte vanligt.

Alternativet för automatisk krympning av databaser har ingen effekt i Hyperscale-databaser.

Om du vill aktivera automatisk krympning kör du följande kommando när du är ansluten till databasen (inte den master databasen).

-- Enable auto-shrink for the current database.
ALTER DATABASE CURRENT
    SET AUTO_SHRINK ON;

Mer information om det här kommandot finns i DATABASE SET-alternativ.

Indexunderhåll efter krympning

Efter att en krympningsoperation är klar kan indexen bli fragmenterade. För de flesta arbetsbelastningar på moderna plattformar är indexfragmentering sannolikt inte att påverka prestandan. För arbetsbelastningar som använder stora indexskanningar kan fragmentering minska läs-I/O-genomströmningen. Om prestandaförsämring inträffar efter att krympningsoperationen är klar, överväg indexunderhåll för att bygga om eller omorganisera indexen. Index-ombyggnader kräver ledigt utrymme i databasen, så de kan orsaka att det tilldelade utrymmet ökar, vilket motverkar effekten av en krympning.

Mer information om indexunderhåll finns i Optimera indexunderhåll för att förbättra frågeprestanda och minska resursförbrukningen.

Krympa stora databaser

När det tilldelade utrymmet i en databas är på hundratals gigabyte eller mer kan krympning ta lång tid. Krympningsoperationer kan pågå timmar, dagar eller veckor för databaser på flera terabyte. Detta avsnitt beskriver processoptimeringar och bästa praxis som gör processen mer effektiv och mindre påverkande för applikationsarbetsbelastningar.

Tips

ShrinkDriver är ett PowerShell-skript som automatiserar och förenklar förminskningsprocessen för stora databaser, och gör den till en enda, observerbar och återupptagbar operation. Skriptet krymper flera filer parallellt, försöker igen när det avbryts och ger detaljerade statusrapporter medan det körs.

Upprätta baslinje för utrymmesanvändning

Innan du börjar krympa samlar du in aktuellt använt och allokerat utrymme i varje databasfil genom att köra följande fråga om utrymmesanvändning:

SELECT file_id,
       CAST (FILEPROPERTY(name, 'SpaceUsed') AS BIGINT) * 8 / 1024. AS space_used_mb,
       CAST (size AS BIGINT) * 8 / 1024. AS space_allocated_mb,
       CAST (max_size AS BIGINT) * 8 / 1024. AS max_size_mb
FROM sys.database_files
WHERE type_desc = 'ROWS';

När krympningen har slutförts kan du köra den här frågan igen och jämföra resultatet med den första baslinjen.

Avkorta datafiler för en snabb men begränsad förbättring

Om du vill uppnå en minskning av det tilldelade utrymmet snabbt, överväg att köra DBCC SHRINKFILE med parametern TRUNCATEONLY . Om det finns något tilldelat men oanvänt utrymme i slutet av filen tar operationen bort det utrymmet snabbt och utan någon datarörelse.

Använd dock inte TRUNCATEONLY om ditt mål är att maximera minskningen av det tilldelade utrymmet. För att uppnå det målet behöver du köra hela krympningsprocessen som beskrivs senare i detta avsnitt. Eftersom den processen förkortar filer i slutet har en separat shrink med TRUNCATEONLY ingen fördel.

Följande exempelkommando förkortar fil-ID 4:

DBCC SHRINKFILE (4, TRUNCATEONLY);

Efter att du kört detta kommando för varje datafil, kör om platsanvändningsfrågan för att se minskningen av tilldelat utrymme, om det finns något. Du kan också se tilldelat utrymme för databasen i Azure-portalen.

Utvärdera indexsidans densitet

Som ett valfritt men rekommenderat steg bör du fastställa den genomsnittliga sidtätheten för index i databasen. För samma mängd data slutförs krympningsoperationer snabbare om sidtätheten är hög, eftersom åtgärden då flyttar färre sidor inom varje fil. Om sidtätheten är låg för vissa index bör du överväga att utföra underhåll på dessa index för att öka sidtätheten innan datafilerna krymps. En högre sidtäthet gör att shrink kan uppnå en djupare minskning av det tilldelade lagringsutrymmet.

Använd följande fråga för att fastställa hur täta sidorna är för alla index i databasen. Siddensitet rapporteras i kolumnen avg_page_space_used_in_percent.

SELECT OBJECT_SCHEMA_NAME(ips.object_id) AS schema_name,
       OBJECT_NAME(ips.object_id) AS object_name,
       i.name AS index_name,
       i.type_desc AS index_type,
       ips.avg_page_space_used_in_percent,
       ips.avg_fragmentation_in_percent,
       ips.page_count,
       ips.alloc_unit_type_desc,
       ips.ghost_record_count
FROM sys.dm_db_index_physical_stats(DB_ID(), DEFAULT, DEFAULT, DEFAULT, 'SAMPLED') AS ips
     INNER JOIN sys.indexes AS i
         ON ips.object_id = i.object_id
        AND ips.index_id = i.index_id
ORDER BY page_count DESC;

Om det finns index med högt sidantal (som rapporteras i kolumnen page_count ) som har sidtäthet lägre än 60–70%, överväg att bygga om eller omorganisera dessa index innan du minskar datafilerna.

För större databaser kan det ta lång tid att köra klart frågan för att fastställa sidtätheten. Om du återskapar eller omorganiserar stora index krävs också betydande tids- och resursanvändning. Indexunderhåll innan krympning kan dock minska krympningstiden och uppnå högre utrymmesbesparingar.

Om det finns flera index med låg sidtäthet kanske du kan återskapa dem parallellt på flera databassessioner för att påskynda processen. Men se till att du inte närmar dig databasens resursgränser genom att göra det. Lämna tillräckligt med resursutrymme för programarbetsbelastningar som kan köras. Övervaka resursförbrukning (CPU, Data IO, Log IO) i Azure portalen eller genom att använda sys.dm_db_resource_stats-vyn. Påbörja ytterligare indexoperationer endast om resursanvändningen på var och en av dessa dimensioner förblir avsevärt lägre än 100%.

Exempel på indexåteruppbyggnadskommando

Följande exempelkommando använder satsen ALTER INDEX för att bygga om ett index och öka dess sidtäthet:

ALTER INDEX [index_name] ON [schema_name].[table_name]
REBUILD WITH (
    FILLFACTOR = 100, MAXDOP = 8, ONLINE = ON (
        WAIT_AT_LOW_PRIORITY (MAX_DURATION = 5 MINUTES, ABORT_AFTER_WAIT = NONE)),
    RESUMABLE = ON
);

Det här kommandot initierar en online- och återupptagningsbar indexåterbyggnad. Med den här åtgärden kan samtidiga arbetsbelastningar fortsätta att använda tabellen medan återskapningen pågår och du kan återuppta återskapningen om den avbryts av någon anledning. Den här typen av återskapande är dock långsammare än en offline-återskapande, vilket blockerar åtkomsten till tabellen. Om inga andra arbetsbelastningar behöver komma åt tabellen under återuppbyggnaden ställer du in ONLINE- och RESUMABLE-alternativen till OFF och tar bort WAIT_AT_LOW_PRIORITY-villkoret.

Mer information om indexunderhåll finns i Optimera indexunderhåll för att förbättra frågeprestanda och minska resursförbrukningen.

Omorganisera index innan krympning

Omorganisering av index innan krympning kan göra krympningsoperationen avsevärt snabbare i två scenarier.

  1. Om databasen uppfyller alla följande kriterier:

    • Den har ett stort antal datafiler (mer än 10).
    • Den har ett stort antal tabeller i databasen (flera hundra eller fler), vilket tillsammans använder mycket utrymme (hundratals gigabyte eller mer).
    • En stor mängd data raderas från vissa tabeller.

    För sådana databaser förkortar omorganisering av index i tabellerna där du raderade data en långvarig fas i krympningsprocessen.

  2. Om databasen innehåller:

    • Stora objektdatatyper (LOB) såsom varchar(max),nvarchar(max),varbinary(max),xml eller liknande datatyper lagrade LOB_DATA i allokeringsenheten.
    • Stora rader som lagras i en ROW_OVERFLOW_DATA allokeringsenhet.
    • Kolumnstoreindex.

    För att få shrink att gå snabbare och frigöra mer utrymme i detta scenario, se till att inkludera klausulen LOB_COMPACTION när du omorganiserar indexen. LOB-komprimering före krympning rekommenderas för alla index som innehåller LOB-kolumner eller stora rader.

    Omorganisering eller återskapande av kolumnlagringsindex innan krympningen kan på liknande sätt öka krymphastigheten och effektiviteten.

Följande exempel visar ett kommando för att omorganisera ett index och utföra LOB-kompaktering:

ALTER INDEX [index_name] ON [schema_name].[table_name]
REORGANIZE WITH(LOB_COMPACTION = ON);

Krymp flera datafiler parallellt

En krympningsoperation som kräver dataförflyttning är en långvarig process. Om databasen har flera datafiler kan du påskynda processen genom att krympa flera datafiler parallellt. Öppna flera databassessioner och använd DBCC SHRINKFILE på varje session med ett annat file_id värde. Likt tidigare indexåterbyggnad, se till att du har tillräckligt med resurser (CPU, data-I/O, logg-I/O) innan du startar varje nytt parallellt krympningskommando.

Följande exempelkommando krymper fil-ID 4 och försöker minska dess tilldelade storlek till 52 000 MB:

DBCC SHRINKFILE (4, 52000);

För att minska det tilldelade filutrymmet till minsta möjliga kör du satsen utan att specificera målstorleken:

DBCC SHRINKFILE (4);

Om du startar för många parallella krympningsoperationer kan du märka hög resursanvändning och konkurrens om lås mellan krympningsoperationer. I de flesta scenarier ligger det optimala antalet parallella krympningsoperationer i intervallet fyra till åtta.

Krymp i inkrementella steg

Om en krympningsåtgärd avbryts oväntat (till exempel på grund av planerat eller oplanerat underhåll) kan en arbetsbelastning börja använda det utrymme som krympningen har frigjort innan krympningen trunkerar filen, vilket gör att en del av de framsteg som krympningen hittills har gjort går förlorade. Eftersom krympning ofta pågår länge är risken för avbrott högre.

För att undvika detta problem, krymp varje fil i mindre, inkrementella steg. I kommandot DBCC SHRINKFILE ställs målet som är mindre än det aktuella tilldelade utrymmet för filen, men större än det använda utrymmet som baslinjeutrymmesanvändningsfrågan returnerar.

Till exempel, om det tilldelade utrymmet för fil-ID 4 är 200 000 MB och du vill krympa till 100 000 MB, kan du först sätta målet till 180 000 MB:

DBCC SHRINKFILE (4, 180000);

Efter att detta kommando minskat den tilldelade storleken till 180 000 MB kan du köra krymp igen, sätta målet först till 160 000 MB, sedan till 140 000 MB, och fortsätta minska målet tills filen når önskad storlek.

Att krympa filer i steg kan ta längre tid, men det minskar risken för att krympningen upprepas för hela filen på grund av oväntade avbrott.

Som utgångspunkt bör du börja med att använda ett inkrement i spannet 10–20 gigabyte. Du kan justera ökningen efter behov för ditt scenario. Större steg kan låta dig slutföra filkrympning snabbare, mindre steg minskar risken att förlora framsteg om krympningen avbryts.

Övervaka krympningsoperationer

För att övervaka förminskningsframsteg för alla samtidigt körande krympningssessioner, använd följande fråga:

SELECT command,
       percent_complete,
       status,
       wait_resource,
       session_id,
       wait_type,
       blocking_session_id,
       cpu_time,
       reads,
       writes,
       CAST (((DATEDIFF(s, start_time, GETDATE())) / 3600) AS VARCHAR) + ' hour(s), '
               + CAST ((DATEDIFF(s, start_time, GETDATE()) % 3600) / 60 AS VARCHAR) + 'min, '
               + CAST ((DATEDIFF(s, start_time, GETDATE()) % 60) AS VARCHAR) + ' sec'
           AS running_time
FROM sys.dm_exec_requests AS r
     LEFT OUTER JOIN sys.databases AS d
         ON r.database_id = d.database_id
WHERE r.command IN ('DbccSpaceReclaim', 'DbccFilesCompact', 'DbccLOBCompact', 'DBCC');

Not

Krympningsprogression kan vara icke-linjär, och värdet i kolumnen percent_complete kan förbli oförändrat under långa perioder, även om krympningen fortfarande pågår. En ökning av värdena för cpu_time, reads eller writes för samma session_id mellan två körningar av frågan innebär att shrink fortsätter att göra framsteg.

När förminskningen är klar för alla datafiler, kör om platsanvändningsfrågan (eller kontrollera i Azure-portalen) för att se den resulterande minskningen av allokerad lagringsstorlek. Om det fortfarande är stor skillnad mellan använt och tilldelat utrymme, bygg om eller omorganisera indexen. En indexombyggnad kan tillfälligt öka det tilldelade utrymmet. Att minska datafilerna igen efter att indexen byggts om leder dock ofta till en djupare minskning av det tilldelade utrymmet.

Tillfälliga fel under krympning

Ibland kan ett krympkommando misslyckas på grund av fel som tidsgränsöverskridanden och dödlägen. Dessa fel är ofta tillfälliga och uppstår inte igen om du upprepar samma kommando. Om shrink misslyckas med ett fel, behåller den framstegen hittills. Kör samma krympningskommando igen för att fortsätta krympa filen.

ShrinkDriver PowerShell-skriptet försöker automatiskt krympa igen när ett tillfälligt fel uppstår. Använd detta skript för att krympa stora databaser.

Följande exempel på T-SQL-skript visar hur man kör shrink för en enda fil i en retry-loop. Loopen försöker automatiskt om operationen upp till ett konfigurerbart antal gånger när ett timeout-fel eller ett deadlock-fel uppstår. Denna återförsöksmetod gäller många andra fel som kan uppstå under krympning.

DECLARE @RetryCount AS INT = 3; -- adjust to configure desired number of retries
DECLARE @Delay AS CHAR (12);

-- Retry loop
WHILE @RetryCount >= 0
BEGIN
    BEGIN TRY
        DBCC SHRINKFILE (1); -- adjust file_id and other shrink parameters

        -- Exit retry loop on successful execution
        SELECT @RetryCount = -1;

    END TRY
    BEGIN CATCH
        -- Retry for the declared number of times without raising
        -- an error if deadlocked or timed out waiting for a lock
        IF ERROR_NUMBER() IN (1205, 49516) AND @RetryCount > 0
        BEGIN
            SELECT @RetryCount -= 1;

            PRINT CONCAT('Retry at ', SYSUTCDATETIME());

            -- Wait for a random period of time between 1 and 10 seconds before retrying
            SELECT @Delay = '00:00:0' + CAST (CAST (1 + RAND() * 8.999 AS DECIMAL (5, 3)) AS VARCHAR (5));

            WAITFOR DELAY @Delay;

        END
        ELSE -- Raise error and exit loop
        BEGIN
            SELECT @RetryCount = -1;

            THROW;

        END
    END CATCH
END

Förutom timeouts och deadlocks kan shrink stöta på fel på grund av vissa kända fel.

Gå igenom felen och åtgärdsstegen i följande avsnitt.

Felnummer 49503

%.*ls: Page %d:%d could not be moved because it is an off-row persistent version store page. Page holdup reason: %ls. Page holdup timestamp: %I64d.

Detta fel uppstår när långvariga aktiva transaktioner genererar radversioner i den persistenta versionslagringen (PVS). Shrink kan inte flytta sidorna som innehåller radversioner.

För att mildra detta fel, vänta tills långvariga transaktioner är klara. Alternativt, identifiera och avsluta långvariga transaktioner, men denna åtgärd kan påverka din applikation om den inte hanterar transaktionsfel på ett smidigt sätt.

Mer information om felsökning av fördröjningar i PVS-rensningen som kan påverka krympning finns i Övervaka och felsök accelererad databasåterställning.

Felnummer 5223

%.*ls: Empty page %d:%d could not be deallocated.

Detta fel kan uppstå under pågående indexunderhållsoperationer såsom ALTER INDEX. Försök förminska kommandot igen när de här åtgärderna har slutförts.

Om detta fel kvarstår kan du behöva bygga om det tillhörande indexet. Kör följande fråga i samma databas där du körde krympningskommandot för att hitta indexet som ska återskapas:

SELECT OBJECT_SCHEMA_NAME(pg.object_id) AS schema_name,
       OBJECT_NAME(pg.object_id) AS object_name,
       i.name AS index_name,
       p.partition_number
FROM sys.dm_db_page_info(DB_ID(), <file_id>, <page_id>, default) AS pg
INNER JOIN sys.indexes AS i
ON pg.object_id = i.object_id
   AND
   pg.index_id = i.index_id
INNER JOIN sys.partitions AS p
ON pg.partition_id = p.partition_id;

Innan du kör denna fråga, ersätt <file_id> och <page_id> platshållarna med de faktiska värdena från felmeddelandet. Till exempel, om meddelandet är: Empty page 1:62669 could not be deallocated, så <file_id> är 1 och <page_id> är 62669.

Återskapa indexet som identifieras av frågan och försök igen med krympningskommandot.

Felnummer 5201

DBCC SHRINKDATABASE: File ID %d of database ID %d was skipped because the file does not have enough free space to reclaim.

Detta fel innebär att datafilen inte kan krympas ytterligare. Du kan gå vidare till nästa datafil.