Aplikácia hlási **Msg 9002** – *The transaction log for database '…' is full due to '…'* – alebo monitoring kričí, že sa zapĺňa LOG disk. Dôvod je priamo v texte chyby (za *due to*) a v stĺpci `log_reuse_wait_desc`. Neriešiš „veľký log“, riešiš **prečo sa log nedá orezať**.
> [!CAUTION]
> Neprepínaj databázu „na skúšku“ do `SIMPLE` a nespúšťaj `SHRINKFILE` na nulu. Prepnutie preruší reťaz log záloh (stratíš obnovu k bodu v čase až do ďalšieho FULL / DIFF) a zmenšený log aj tak hneď znova narastie.
## 1. Zisti dôvod
1. Spusti [Transaction log – obsadenie, reuse wait a VLF](script.php?id=33&s=transaction-log-obsadenie-reuse-wait-a-vlf) – uvidíš `log_reuse_wait_desc`, `active_log_size_mb`, počet VLF a čas posledného log backupu.
2. Pozri, či je plný **disk** (log nemá kam rásť) alebo log narazil na **MAXSIZE**. Ak je to MAXSIZE a na disku je miesto, stačí zvýšiť limit.
3. Podľa `log_reuse_wait_desc` pokračuj vetvou nižšie.
```sql
SELECT name, recovery_model_desc, log_reuse_wait_desc
FROM sys.databases
WHERE name = N'MojaDB';
```
## 2. Vetvy podľa log_reuse_wait_desc
| Dôvod | Čo to znamená | Čo urobiť |
|---|---|---|
| `LOG_BACKUP` | FULL / BULK_LOGGED recovery a log backup dlho nebežal (najčastejšie). | Urob log backup (job alebo ručne). Ak log nikdy nebol zálohovaný, môžu byť potrebné **dva** log backupy za sebou. Over, prečo job nebežal – [Zlyhané joby](script.php?id=40&s=sql-agent-joby-ktore-naposledy-zlyhali). |
| `ACTIVE_TRANSACTION` | Dlhá alebo zabudnutá transakcia drží začiatok aktívnej časti logu. | [Otvorené transakcie](script.php?id=15&s=otvorene-transakcie-kto-ich-drzi-a-ako-dlho) a [Detail blockera](script.php?id=14&s=detail-blockera-aj-spiaca-session-s-otvorenou-transakciou). Dohodni COMMIT / ROLLBACK s vlastníkom aplikácie. `KILL` až ako posledná možnosť – rollback môže trvať dlhšie než transakcia bežala. |
| `AVAILABILITY_REPLICA` | Sekundárna AG replika ešte nemá log zapísaný (alebo je pozastavená / odpojená). | [Always On AG – stav replík](script.php?id=42&s=always-on-ag-stav-replik-a-synchronizacie): `log_send_queue_kb`, `redo_queue_kb`, stav synchronizácie. Obnov pozastavený data movement, rieš sieť / disk na sekundárke. Odobratie databázy z AG je krajné riešenie. |
| `REPLICATION` | Log Reader Agent (transakčná replikácia) alebo CDC ešte nespracoval záznamy. | Skontroluj Log Reader Agent / CDC capture job, chyby v Replication Monitore. `DBCC OPENTRAN` ukáže najstaršiu replikovanú transakciu. |
| `ACTIVE_BACKUP_OR_RESTORE` | Beží FULL / DIFF záloha (alebo restore). | [Priebeh BACKUP / RESTORE / DBCC](script.php?id=21&s=priebeh-backup-restore-dbcc) – počkaj, kým skončí, alebo zálohu vedome zruš. |
| `CHECKPOINT` | Od posledného orezania neprebehol checkpoint. | `USE MojaDB; CHECKPOINT;` – zvyčajne sa vyrieši samo. |
| `OLDEST_PAGE`, `LOG_SCAN`, `DATABASE_SNAPSHOT_CREATION` | Krátkodobé stavy. | Väčšinou netreba nič; ak `OLDEST_PAGE` trvá, pozri `TARGET_RECOVERY_TIME`. |
## 3. Núdzovo: kam s logom, kým riešiš príčinu
1. **Pridaj druhý log súbor na iný disk**, kde je miesto. Je to dočasné riešenie, nie trvalý stav:
```sql
ALTER DATABASE MojaDB
ADD LOG FILE (NAME = N'MojaDB_log_tmp', FILENAME = N'<iný disk>/MojaDB_log_tmp.ldf',
SIZE = 8GB, FILEGROWTH = 1GB);
```
2. Po vyriešení príčiny a log backupe dočasný súbor odober (`ALTER DATABASE … REMOVE FILE`) – podarí sa, až keď v ňom nie je aktívna časť logu (niekedy treba ďalší log backup).
3. Ak sa databáza počas 9002 dostala do stavu `RECOVERY_PENDING`, po uvoľnení miesta ju vráť `ALTER DATABASE MojaDB SET ONLINE;`.
## 4. Kedy a ako zmenšiť log (SHRINKFILE)
- Len ak log narástol **jednorazovo** (veľký import, rebuild indexov, zaseknutá replika) a príčina je preč.
- Zmenši na **cieľovú prevádzkovú veľkosť** (napr. 1,5 × najväčšia bežná aktivita medzi log backupmi), nikdy nie na nulu:
```sql
USE MojaDB;
DBCC SHRINKFILE (N'MojaDB_log', 16384); -- cieľ v MB
```
- Ak sa log nezmenší, aktívna časť je na konci súboru – urob log backup a zopakuj.
- Po zmenšení nastav rozumný `FILEGROWTH` v MB (napr. 1–8 GB), aby nevznikli tisíce malých VLF.
## 5. Over, že je hotovo
- `log_reuse_wait_desc` = `NOTHING` (alebo `LOG_BACKUP` krátko pred ďalším backupom),
- `active_log_size_mb` výrazne pod `total_log_size_mb`,
- log backup job beží podľa plánu a [Posledné zálohy](script.php?id=3&s=posledne-zalohy-kazdej-databazy) neukazujú meškanie.
## 6. Prevencia
- SQL Agent alert na **chybu 9002** a na percento zaplnenia logu (perf counter *Percent Log Used*).
- Autogrowth v **MB**, nie v percentách; MAXSIZE vedome.
- Kapacita disku a úložiska záloh počíta s log backupmi počas údržby (rebuild indexov generuje veľa logu).
- Pre AG sleduj send / redo queue, pre replikáciu latenciu Log Reader Agenta.
> [!TIP]
> Pri incidente si zapíš čas, databázu, `log_reuse_wait_desc` a čo si urobil – rovnaká šablóna ako v [Prvej pomoci DBA](script.php?id=47&s=prva-pomoc-dba-ktory-skript-spustit-pri-probleme).
## Zdroje
- [Troubleshoot a full transaction log (error 9002)](https://learn.microsoft.com/en-us/sql/relational-databases/logs/troubleshoot-a-full-transaction-log-sql-server-error-9002)
- [Tail-log backups](https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/tail-log-backups-sql-server)LOG disk je plný – čo robiť krok za krokom (chyba 9002)
Chyba 9002 „The transaction log for database is full“: ako zistiť, čo drží log (log_reuse_wait_desc), čo urobiť pri LOG_BACKUP, ACTIVE_TRANSACTION, AVAILABILITY_REPLICA a ďalších dôvodoch, kedy pridať log súbor a kedy (ne)zmenšovať.