SHRINKFILE Failure - ทำไมการเพิ่มขนาดไฟล์จึงแก้ไขได้?


10

ฉันใช้SHRINKFILEการดำเนินการบางอย่างเพื่อทำความสะอาดไฟล์เล็ก ๆ ที่ไม่จำเป็นในกลุ่มไฟล์ สำหรับการย่อขนาดหนึ่งคำสั่งด้านล่างส่งผลให้เกิดข้อผิดพลาด:

DBCC SHRINKFILE (N'myfile' , EMPTYFILE)'

ID ไฟล์ x ของ ID ฐานข้อมูล x ไม่สามารถย่อขนาดได้เนื่องจากเป็นกระบวนการที่ถูกย่อโดยกระบวนการอื่นหรือว่างเปล่า

มันไม่ได้ว่างเปล่าหรือหดตัว มันกำลังถูกรันบนฐานข้อมูลที่ไม่ได้ใช้งานโดยทุกคนยกเว้นตัวฉันเอง ไม่ได้เปิดใช้งานการย่อขนาดอัตโนมัติและไม่เคยเป็น แต่มีอยู่ shrinks คู่มือการดำเนินการเกี่ยวกับฐานข้อมูลนี้เป็นประจำก่อนที่จะฉันได้รับในมือของฉันที่มันถ้าเรื่องที่ทุก

บนSQLServerCentralเธรดจากทศวรรษที่ผ่านมาแนะนำการเพิ่ม MB ไม่กี่ MB ลงในแฟ้มได้เนื่องจาก "ตั้งค่าตัวนับภายในหรือสวิตช์ภายในที่บอกว่ามันไม่ได้อยู่ในช่วงหดตัวในขณะนี้"

สิ่งนี้ใช้ได้ - ยอดเยี่ยม แต่ทุกคนสามารถอธิบายรายละเอียดที่มากขึ้นว่า / ทำไมมันถึงเกี่ยวกับ SQL Server internals?


1
ไม่สามารถบอกคำตอบของคุณได้ แต่การลุกขึ้นเนื่องจากมันเป็นกลอุบายที่ใช้ง่ายที่จะรู้ว่าฉันเคยเจอสถานการณ์นี้ในอนาคตหรือไม่!
John Eisbrener

หากคุณสามารถทำซ้ำอาจตั้งค่าสถานะบางอย่างในหน้าส่วนหัวของไฟล์ที่ได้รับการตั้งค่าในช่วงหดตัว?
Martin Smith

ใช่ฉันอาจให้ช็อตในตัวอย่างทดสอบ แต่นี่เป็นการกระทุ้งอย่างแน่นอนไม่มีความหรูหราในการลองทำซ้ำที่นั่น
LowlyDBA

คำตอบ:


5

ฉันแหย่ในหน้าส่วนหัวของไฟล์ตามที่ Martin Smith แนะนำไว้ในความคิดเห็น ฉันคิดว่านี่เป็นส่วนหนึ่งของคำตอบ แต่ส่วนใหญ่เป็นการเก็งกำไรจากการสังเกตการเปลี่ยนแปลงค่าแฟล็กหน้าส่วนหัวของไฟล์ระหว่างการลดขนาดและการดำเนินการอื่น ๆ


ก่อนอื่นฉันสร้างฐานข้อมูลเพื่อทดสอบรวมถึงกลุ่มไฟล์รอง:

CREATE DATABASE [Shrinkfile_Test]
ON PRIMARY
(
    NAME = N'Shrinkfile_Test',
    FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.SQL2016\MSSQL\DATA\Shrinkfile_Test.mdf',
    SIZE = 8192KB,
    FILEGROWTH = 65536KB
),
FILEGROUP [SECONDARY]
(
    NAME = N'ShrinkFile_Test_Secondary',
    FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.SQL2016\MSSQL\DATA\ShrinkFile_Test_Secondary.ndf',
    SIZE = 1024KB,
    FILEGROWTH = 65536KB
)
LOG ON
(
    NAME = N'Shrinkfile_Test_log',
    FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.SQL2016\MSSQL\DATA\Shrinkfile_Test_log.ldf',
    SIZE = 73728KB,
    FILEGROWTH = 65536KB 
)
GO

USE Shrinkfile_Test;
GO

ฉันดูที่ "หน้า 0" สำหรับไฟล์รองซึ่งคือ file_id 3:

DBCC TRACEON (3604);
GO
DBCC PAGE (N'Shrinkfile_Test', 3, 0, 3);

มีข้อมูลที่เรียกว่าเป็นที่มีค่าของm_flagBits0x208

หากฉันลบไฟล์นี้:

DBCC SHRINKFILE (N'ShrinkFile_Test_Secondary' , EMPTYFILE);

m_flagbitsฟิลด์นั้นยังคงเหมือนเดิม ( 0x208) ไม่น่าสนใจ แต่ตอนนี้ฉันอยู่ในสถานการณ์ที่คุณรายงาน: ถ้าฉันพยายามลบไฟล์อีกครั้งฉันได้รับข้อผิดพลาดนี้:

ไฟล์ ID 3 ของ ID ฐานข้อมูล 19 ไม่สามารถย่อขนาดได้เนื่องจากกำลังถูกย่อโดยกระบวนการอื่นหรือว่างเปล่า

ฉันจะลองขยายไฟล์ (โซลูชันที่เหมาะกับคุณ):

ALTER DATABASE ShrinkFile_Test
MODIFY FILE
(
    NAME = ShrinkFile_Test_Secondary,
    SIZE = 1025KB
);
GO

ตอนนี้m_flagbitsเป็น0x8!

ณ จุดนี้การล้างไฟล์อีกครั้งจะส่งกลับค่าสำเร็จ0x208ตามที่คุณคาดหวัง

สิ่งที่ฉันคิดว่าน่าสนใจคือถ้าฉันทำสิ่งนี้หลังจากที่ขยายไฟล์กลับออกไป (ค่า AKA flagbits คือ0x8):

USE [master]
GO
ALTER DATABASE [Shrinkfile_Test] MODIFY FILEGROUP [SECONDARY] READONLY
GO

ไฟล์ที่ถูกทำเครื่องหมายเป็นis_read_onlyในsys.databasesตารางและมีการตั้งค่ากลับไป m_flagbits ดังนั้นจึงปรากฏว่ามีการตั้งค่าสถานะระดับไฟล์คล้ายกันเมื่อทำการย่อขนาดไฟล์และเมื่อตั้งค่าให้อ่านอย่างเดียว0x208

สิ่งที่ฉันคาดเดาได้ดีที่สุดคือค่านี้ใช้พร้อมกับการตั้งค่าสถานะ (ภายใน) อื่น ๆ เพื่อระบุว่าไฟล์มีสิทธิ์ถูกย่อ การขยายไฟล์ดูเหมือนจะยกเลิกการตั้งค่าสถานะนั้น (อย่างน้อยหนึ่งไฟล์ที่มองเห็นได้m_flagbits)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.