Categories
Database Backup

** Discover expert strategies for preventing and resolving MSSQL transaction log full errors (Error 9002). Learn rapid recovery techniques, VLF management, and architectural best practices for DBAs.

برای مدیران پایگاه داده (DBAs) و مهندسان DevOps که مدیریت Microsoft SQL Server را بر عهده دارند، تعداد کمی از هشدارها به اندازه خطای 9002 باعث اضطراب فوری می‌شوند: گزارش تراکنش (Transaction Log) برای پایگاه داده «X» پر است. هنگامی که گزارش تراکنش پر می‌شود و نمی‌تواند رشد کند، پایگاه داده عملاً فقط‌خواندنی (Read-only) می‌شود. تمام عملیات‌های INSERT، UPDATE و DELETE متوقف می‌شوند، تراکنش‌های برنامه با شکست مواجه می‌شوند و عملیات تولید به بن‌بست می‌رسد.

درک معماری زیربنایی گزارش تراکنش SQL Server، تشخیص دقیق علت اصلی و اجرای سریع روش‌های بازیابی، مهارت‌های حیاتی برای حفظ در دسترس بودن بالا (High Availability) هستند. این راهنمای جامع به بررسی مکانیسم‌های گزارش تراکنش، نحوه حل مشکل پر شدن گزارش در شرایط اضطراری و بهترین شیوه‌های معماری برای جلوگیری از تکرار آن می‌پردازد.

درک معماری گزارش تراکنش SQL Server

برای عیب‌یابی مؤثر گزارش تراکنش پر شده، ابتدا باید درک کنید که SQL Server چگونه داده‌ها را می‌نویسد و مدیریت می‌کند.

گزارش‌نویسی پیش‌نویس (Write-Ahead Logging – WAL)

SQL Server از پروتکل Write-Ahead Logging (WAL) استفاده می‌کند. هر زمان که تغییری در داده‌ها رخ می‌دهد، تغییر ابتدا در گزارش تراکنش در حافظه نوشته می‌شود و سپس قبل از به‌روزرسانی صفحات داده واقعی در فایل‌های پایگاه داده (MDF/NDF)، به فایل گزارش فیزیکی روی دیسک منتقل (Flush) می‌شود. این امر انطباق با ACID (اتمی بودن، سازگاری، جداسازی، پایداری) را تضمین می‌کند و اطمینان می‌دهد که در صورت بروز خرابی، SQL Server می‌تواند تراکنش‌ها را دوباره اجرا (Roll forward) یا لغو (Roll back) کند.

فایل‌های گزارش مجازی (VLFs) و گزارش‌نویسی چرخشی

به‌صورت داخلی، فایل گزارش تراکنش فیزیکی (LDF) به بخش‌های منطقی کوچک‌تری به نام فایل‌های گزارش مجازی (VLFs) تقسیم می‌شود. گزارش تراکنش به‌صورت چرخشی عمل می‌کند. همان‌طور که رکوردهای گزارش نوشته می‌شوند، یک VLF را پر کرده و به بعدی می‌روند.

هنگامی که گزارش به انتهای فایل فیزیکی می‌رسد، سعی می‌کند به ابتدای آن بازگردد. با این حال، تنها در صورتی می‌تواند یک VLF را بازنویسی کند که آن VLF به‌عنوان غیرفعال علامت‌گذاری شده باشد. اگر تمام VLFها فعال باشند (به این معنی که حاوی رکوردهای گزارشی هستند که هنوز توسط SQL Server مورد نیاز است)، گزارش نمی‌تواند به ابتدا بازگردد. اگر رشد خودکار (Auto-growth) فعال باشد و فضای دیسک موجود باشد، فایل فیزیکی رشد می‌کند. اگر دیسک پر باشد یا رشد خودکار محدود شده باشد، با خطای 9002 مواجه می‌شوید.

کوتاه‌سازی گزارش (Truncation) در مقابل کوچک‌سازی گزارش (Shrinking)

یک تصور غلط رایج این است که کوتاه‌سازی گزارش، اندازه فایل فیزیکی را کاهش می‌دهد.
* کوتاه‌سازی گزارش (Log Truncation): فرآیند علامت‌گذاری VLFهای فعال به‌عنوان غیرفعال، که فضا را برای استفاده مجدد در دسترس قرار می‌دهد. این کار اندازه فایل LDF روی دیسک را کاهش نمی‌دهد.
* کوتاه‌سازی فایل (Log Shrinking): فرآیند کاهش فیزیکی اندازه فایل LDF و بازگرداندن فضا به سیستم‌عامل.

در مدل بازیابی Full، کوتاه‌سازی گزارش تنها زمانی رخ می‌دهد که پشتیبان‌گیری از گزارش تراکنش با موفقیت انجام شود (با فرض اینکه هیچ فرآیند دیگری گزارش را فعال نگه نداشته باشد).

تشخیص خطای «گزارش تراکنش پر است» (خطای 9002)

هنگامی که گزارش پر است، اولین قدم شما نباید اضافه کردن کورکورانه فضای دیسک یا کوچک کردن فایل‌ها باشد. شما باید شناسایی کنید که چرا گزارش نمی‌تواند کوتاه‌سازی شود. SQL Server یک مکانیسم داخلی برای اطلاع دقیق از آنچه مانع استفاده مجدد از گزارش می‌شود، از طریق نمای کاتالوگ sys.databases ارائه می‌دهد.

دستور T-SQL زیر را برای شناسایی گلوگاه اجرا کنید:

SELECT 
    name AS DatabaseName, 
    recovery_model_desc AS RecoveryModel, 
    log_reuse_wait_desc AS LogReuseWaitReason
FROM sys.databases
WHERE name = 'YourDatabaseName';

همچنین می‌توانید میزان استفاده فعلی از فضای گزارش‌های تراکنش خود را با استفاده از دستور زیر بررسی کنید:

DBCC SQLPERF(LOGSPACE);

وضعیت‌های رایج log_reuse_wait_desc

  1. LOG_BACKUP: پایگاه داده در مدل بازیابی Full یا Bulk-Logged است و اخیراً از گزارش تراکنش پشتیبان‌گیری نشده است. این رایج‌ترین علت است.
  2. ACTIVE_TRANSACTION: یک تراکنش طولانی‌مدت (مثلاً بازسازی عظیم ایندکس یا یک تراکنش فراموش‌شده و تایید نشده) گزارش را فعال نگه داشته است.
  3. REPLICATION / CDC: قابلیت Transactional Replication یا Change Data Capture (CDC) فعال است و Log Reader Agent هنوز تراکنش‌ها را پردازش نکرده است.
  4. AVAILABILITY_REPLICA: در یک گروه در دسترس AlwaysOn، یک کپی ثانویه قطع شده یا خیلی کند همگام‌سازی می‌شود و کپی اولیه را مجبور می‌کند رکوردهای گزارش را تا زمانی که در کپی ثانویه ثبت شوند، نگه دارد.

استراتژی‌های بازیابی سریع: حل مشکل در محیط تولید

بسته به log_reuse_wait_desc بازگردانده شده، واکنش اضطراری شما متفاوت خواهد بود. در اینجا استراتژی‌های بازیابی سریع برای رایج‌ترین سناریوها آورده شده است.

سناریو 1: پشتیبان‌گیری‌های گزارش از دست رفته یا ناموفق (LOG_BACKUP)

اگر نوع انتظار LOG_BACKUP باشد، راه‌حل ساده است: باید از گزارش تراکنش پشتیبان بگیرید.

BACKUP LOG [YourDatabaseName] 
TO DISK = 'N:BackupsYourDatabaseName_EmergencyLog.trn' 
WITH COMPRESSION, STATS = 10;

پس از تکمیل پشتیبان‌گیری، VLFهای غیرفعال کوتاه‌سازی می‌شوند و SQL Server عملیات عادی را از سر می‌گیرد. اگر درایو پشتیبان شما پر است، ممکن است لازم باشد در یک اشتراک شبکه موقت یا یک دستگاه تهی (Null device) پشتیبان بگیرید (این کار به شدت توصیه نمی‌شود مگر اینکه پایگاه داده به راحتی قابل بازسازی باشد، زیرا زنجیره گزارش را می‌شکند):

-- هشدار: این کار زنجیره گزارش را می‌شکند و بازیابی در لحظه (Point-in-time) را به خطر می‌اندازد.
-- تنها در صورت ضرورت مطلق استفاده کنید و بلافاصله با یک پشتیبان کامل (FULL) دنبال کنید.
BACKUP LOG [YourDatabaseName] TO DISK = 'NUL';

سناریو 2: تراکنش‌های فعال طولانی‌مدت (ACTIVE_TRANSACTION)

اگر یک تراکنش واحد ساعت‌ها در حال اجرا بوده باشد، از کوتاه‌سازی گزارش برای کل مدت زمان جلوگیری می‌کند. ابتدا تراکنش مشکل‌ساز را شناسایی کنید:

DBCC OPENTRAN('YourDatabaseName');

این دستور قدیمی‌ترین تراکنش فعال و شناسه فرآیند سرور (SPID) آن را برمی‌گرداند. می‌توانید با پرس‌وجو از نماهای مدیریت پویا (DMVs)، جزئیات بیشتری درباره کاری که SPID انجام می‌دهد به دست آورید:

SELECT 
    s.session_id,
    s.login_name,
    s.host_name,
    r.start_time,
    r.status,
    r.command,
    t.text AS QueryText
FROM sys.dm_exec_sessions s
JOIN sys.dm_exec_requests r ON s.session_id = r.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE s.session_id = <SPID_FROM_DBCC_OPENTRAN>;

اگر تراکنش یک پرس‌وجوی مخرب یا یک فرآیند متوقف‌شده است، ممکن است لازم باشد آن را خاتمه دهید تا گزارش آزاد شود.

KILL <SPID>;

توجه: کشتن یک تراکنش عظیم باعث فعال شدن Rollback می‌شود که می‌تواند زمان قابل توجهی طول بکشد و به‌طور موقت فعالیت گزارش اضافی ایجاد کند. در حین Rollback، سرویس SQL Server را مجدداً راه‌اندازی نکنید، در غیر این صورت پایگاه داده پس از راه‌اندازی مجدد وارد حالت بازیابی می‌شود.

سناریو 3: تخصیص فضای اضطراری (دیسک 100٪ پر است)

اگر فایل LDF کل درایو را مصرف کرده است، حتی نمی‌توانید پشتیبان‌گیری کنید زیرا SQL Server برای ثبت خودِ رویداد پشتیبان‌گیری به مقدار کمی فضای گزارش نیاز دارد. در این سناریو، باید یک فایل گزارش ثانویه در درایو دیگری با فضای موجود اضافه کنید.

ALTER DATABASE [YourDatabaseName]
ADD LOG FILE 
(
    NAME = N'YourDatabaseName_Log2',
    FILENAME = N'E:TempLogsYourDatabaseName_Log2.ldf',
    SIZE = 5GB,
    MAXSIZE = 50GB,
    FILEGROWTH = 1GB
);

این کار بلافاصله به SQL Server فضای تنفس می‌دهد. هنگامی که پایگاه داده آنلاین شد، یک پشتیبان از گزارش تراکنش بگیرید، فایل گزارش ثانویه را خالی کنید و آن را حذف کنید:

-- 1. برای کوتاه‌سازی گزارش، یک پشتیبان از گزارش بگیرید
BACKUP LOG [YourDatabaseName] TO DISK = '...';

-- 2. فایل گزارش موقت را خالی کنید
DBCC SHRINKFILE (N'YourDatabaseName_Log2', EMPTYFILE);

-- 3. فایل گزارش موقت را حذف کنید
ALTER DATABASE [YourDatabaseName] REMOVE FILE [YourDatabaseName_Log2];

بهترین شیوه‌ها برای پیشگیری و مدیریت گزارش تراکنش

عیب‌یابی واکنشی استرس‌زا است و بر SLAها تأثیر می‌گذارد. اجرای بهترین شیوه‌های معماری و عملیاتی پیشگیرانه برای پایداری پایگاه داده سازمانی ضروری است.

1. پیاده‌سازی یک استراتژی پشتیبان‌گیری قوی و خودکار

اگر پایگاه داده در مدل بازیابی Full باشد، پشتیبان‌گیری‌های مکرر از گزارش تراکنش الزامی است. بسته به هدف نقطه بازیابی (RPO) و حجم تراکنش، پشتیبان‌گیری از گزارش باید هر 5 تا 15 دقیقه انجام شود.

راه‌حل‌های پشتیبان‌گیری سازمانی مانند CloudSave این فرآیند را به‌طور قابل توجهی ساده می‌کنند. با ادغام مستقیم با SQL Server از طریق VDI (رابط دستگاه مجازی)، CloudSave به مدیران پایگاه داده اجازه می‌دهد تا پشتیبان‌گیری‌های گزارش تراکنش با فرکانس بالا و مبتنی بر سیاست را پیکربندی کنند. این امر تضمین می‌کند که گزارش‌ها به‌طور مداوم کوتاه‌سازی، به‌صورت ایمن رمزگذاری و در فضای ذخیره‌سازی ابری غیرقابل تغییر ذخیره می‌شوند و بدون نیاز به کارهای پیچیده SQL Agent سفارشی، از وضعیت انتظار LOG_BACKUP جلوگیری می‌کند.

2. تنظیم اندازه مناسب گزارش تراکنش و مدیریت VLFها

تکیه بر رشد خودکار برای مدیریت اندازه گزارش تراکنش یک الگوی ضد (Anti-pattern) خطرناک است. عملیات رشد خودکار پرهزینه هستند و پردازش تراکنش را تا زمانی که دیسک با صفر مقداردهی اولیه شود، متوقف می‌کنند (مگر اینکه Instant File Initialization فعال باشد که برای فایل‌های گزارش اعمال نمی‌شود).

علاوه بر این، رشد خودکار مکرر و کوچک (مثلاً رشد 10٪ یا 50 مگابایت در هر بار) منجر به تکه‌تکه شدن VLF (VLF fragmentation) می‌شود. یک گزارش تراکنش با هزاران VLF کوچک، زمان راه‌اندازی پایگاه داده، عملکرد پشتیبان‌گیری و تأخیر همانندسازی (Replication) را به‌شدت کاهش می‌دهد.

  • اندازه اولیه گزارش را تعیین کنید: بزرگترین عملیات نگهداری خود (مانند بازسازی ایندکس) را تحلیل کنید و اندازه فایل LDF را طوری تعیین کنید که بدون رشد، آن‌ها را در خود جای دهد.
  • رشد خودکار ثابت تنظیم کنید: رشد خودکار را از درصد به یک اندازه ثابت (مثلاً 1 گیگابایت یا 5 گیگابایت) تغییر دهید تا اطمینان حاصل شود که VLFها با اندازه مناسب ایجاد می‌شوند.

می‌توانید تعداد VLF خود را با استفاده از پرس‌وجوی زیر بررسی کنید (برای SQL Server 2017 و بالاتر):

SELECT 
    db_name(database_id) AS DatabaseName,
    COUNT(vlf_sequence_number) AS VLF_Count
FROM sys.dm_db_log_info(DB_ID('YourDatabaseName'));

اگر تعداد VLF شما بیش از 500 است، در نظر داشته باشید که در یک دوره خلوت، گزارش را به حداقل اندازه کوچک کنید و به‌صورت دستی آن را در قطعات بزرگ به اندازه مورد نیاز خود بازگردانید.

3. بهینه‌سازی عملیات نگهداری ایندکس

بازسازی ایندکس عملیاتی است که به‌طور کامل ثبت می‌شود، حتی در مدل بازیابی Bulk-Logged (بسته به نوع ایندکس). بازسازی یک ایندکس 500 گیگابایتی حداقل 500 گیگابایت رکورد گزارش تراکنش تولید می‌کند.

برای کاهش تورم گزارش در حین نگهداری:
* هنگام بازسازی ایندکس‌ها از SORT_IN_TEMPDB = ON استفاده کنید. این کار مرحله مرتب‌سازی را به TempDB منتقل می‌کند و بار روی گزارش تراکنش پایگاه داده کاربر را کاهش می‌دهد.
* در صورت امکان از بازسازی ایندکس به سازماندهی مجدد (Reorganize) ایندکس تغییر وضعیت دهید، زیرا سازماندهی مجدد از نظر گزارش کارآمدتر است و می‌تواند بدون لغو کل عملیات، متوقف شود.
* عملیات‌های بزرگ DELETE یا UPDATE را دسته‌بندی کنید. به‌جای حذف 10 میلیون ردیف در یک تراکنش، آن‌ها را در دسته‌های 50,000 تایی حذف کنید، تایید کنید و اجازه دهید پشتیبان‌گیری‌های گزارش، گزارش را بین دسته‌ها کوتاه‌سازی کنند.

4. نظارت بر توپولوژی‌های در دسترس بودن بالا و همانندسازی

در گروه‌های در دسترس AlwaysOn، کپی اولیه نمی‌تواند گزارش خود را کوتاه‌سازی کند تا زمانی که رکوردهای گزارش در تمام کپی‌های ثانویه همگام و غیرهمگام ثبت شوند.

اگر یک کپی ثانویه آفلاین شود، یا اگر پهنای باند شبکه نتواند با نرخ تولید تراکنش کپی اولیه همگام شود، صف ارسال کپی اولیه رشد می‌کند و گزارش پر می‌شود (نوع انتظار AVAILABILITY_REPLICA).

نظارت قوی برای شمارنده عملکرد SQLServer:Replica > Log Send Queue پیاده‌سازی کنید. اگر یک کپی ثانویه به‌طور دائم از دست رفت، باید آن را از گروه در دسترس حذف کنید یا انتقال داده را متوقف کنید تا گزارش اولیه بتواند کوتاه‌سازی شود.

نتیجه‌گیری

مواجهه با یک گزارش تراکنش پر، یک چالش معمول برای مدیران پایگاه داده است، اما لزوماً نباید منجر به خرابی طولانی‌مدت شود. با درک مکانیسم‌های Write-Ahead Logging و VLFها، می‌توانید به‌سرعت علت اصلی را با استفاده از sys.databases تشخیص دهید و استراتژی بازیابی سریع صحیح را اعمال کنید.

پایداری بلندمدت به دور شدن از اصلاحات واکنشی بستگی دارد. تعیین اندازه اولیه فایل‌های گزارش، بهینه‌سازی روتین‌های نگهداری و استفاده از پلتفرم‌های پشتیبان‌گیری در سطح سازمانی مانند CloudSave برای اعمال برنامه‌های پشتیبان‌گیری گزارش دقیق و خودکار، تضمین می‌کند که گزارش‌های تراکنش شما سالم، کوتاه‌سازی شده و آماده پشتیبانی از بارهای کاری تولید با توان عملیاتی بالا باقی می‌مانند.