📋 SQL Server Transaction Logs – Alles was Sie wissen müssen
Aufbau, Verwaltung, Recovery-Modelle, Log-Shipping, Shrink & VLF – Best Practices für einen gesunden Transaktionslog
📌 Was ist das Transaktionslog (Transaction Log)?
GRUNDLAGEN
Das Transaktionslog (.ldf-Datei) ist eine der wichtigsten Komponenten jeder SQL Server-Datenbank. Es zeichnet jede Änderung an der Datenbank auf – und zwar bevor die Änderung auf die Datendatei (.mdf) geschrieben wird. Dies ermöglicht:
- ✨ Point-in-Time-Wiederherstellung (bis zu einer bestimmten Sekunde)
- ⚡ Transaktionssicherheit (Rollback bei Fehlern)
- 🔄 Log Shipping, Always On, Spiegelung – alle Hochverfügbarkeitslösungen basieren auf dem Transaktionslog
- 🧹 Replikation und Change Data Capture (CDC)
💡 Wichtig: Das Transaktionslog ist sequenziell und zirkulär – es wird nicht einfach gelöscht, sondern logisch abgeschnitten. Wenn Sie keine Log-Backups durchführen, wächst es bei vollem Wiederherstellungsmodell unbegrenzt.
🧩 Aufbau des Transaktionslogs – VLFs (Virtual Log Files)
INTERN
Das Transaktionslog ist intern in mehrere kleinere Segmente unterteilt, die sog. Virtual Log Files (VLFs). Die Anzahl der VLFs wird beim Anlegen oder beim automatischen Wachstum der Log-Datei festgelegt. Eine zu hohe Anzahl von VLFs (mehrere Tausend) kann die Performance von Backups, Restores und Recovery-Vorgängen beeinträchtigen.
-- Anzahl und Größe der VLFs anzeigen
DBCC LOGINFO;
-- Moderne Alternative (SQL Server 2012+), detaillierte VLF-Info
SELECT
database_id,
file_id,
vlf_begin_offset,
vlf_size_mb,
vlf_sequence_number,
vlf_active
FROM sys.dm_db_log_info(DB_ID('IhreDatenbank'))
ORDER BY vlf_sequence_number;
📌 Best Practice: Vermeiden Sie zu viele VLFs (> 1000). Bei neu anzulegenden Datenbanken setzen Sie die Log-Größe auf einen realistischen Wert (z. B. 1 GB) und verwenden Sie
FILEGROWTH in MB (nicht in Prozent). So verhindern Sie eine starke Fragmentierung der VLFs.
🔄 Die drei Wiederherstellungsmodelle (Recovery Models)
RECOVERY
Das Recovery Model bestimmt, wie SQL Server das Transaktionslog handhabt und welche Wiederherstellungsoptionen Ihnen zur Verfügung stehen.
1. SIMPLE (einfach)
- Das Log wird bei jedem Checkpoint automatisch abgeschnitten.
- Keine Point-in-Time-Wiederherstellung möglich.
- Log-Backups sind nicht erlaubt.
- Ideal für Testdatenbanken oder wenn Datenverlust bis zur letzten Sicherung akzeptabel ist.
- Jede Transaktion wird vollständig protokolliert.
- Erfordert regelmäßige Log-Backups, sonst wächst das Log unbegrenzt.
- Ermöglicht Point-in-Time-Wiederherstellung.
- Standard für Produktionsdatenbanken mit hohen Konsistenzanforderungen.
- Minimiertes Logging für Massenoperationen (z. B.
SELECT INTO,BULK INSERT). - Point-in-Time-Wiederherstellung ist innerhalb der Massenoperation nicht möglich.
- Gut geeignet für nächtliche ETL-Prozesse (kurzzeitig).
-- Recovery Model ändern
ALTER DATABASE [MeineDB] SET RECOVERY FULL;
ALTER DATABASE [MeineDB] SET RECOVERY SIMPLE;
ALTER DATABASE [MeineDB] SET RECOVERY BULK_LOGGED;
-- Aktuelles Modell prüfen
SELECT name, recovery_model_desc FROM sys.databases;
🚨 Achtung: Wenn Sie von SIMPLE auf FULL wechseln, müssen Sie sofort ein vollständiges Backup erstellen, um die Log-Kette zu starten. Andernfalls kann das Log noch nicht abgeschnitten werden.
💾 Transaktionslog-Backups – Rhythmus und Größe
BACKUP
Bei FULL oder BULK_LOGGED sind regelmäßige Log-Backups essenziell. Sie dienen nicht nur der Wiederherstellbarkeit, sondern auch dem Abschneiden des Logs. Typische Frequenzen:
- Hochfrequente OLTP-Systeme: alle 15–30 Minuten
- Standard-Workload: stündlich
- Nacht-Etl: alle 4 Stunden
-- Transaktionslog-Backup
BACKUP LOG [MeineDB]
TO DISK = N'D:\Backups\MeineDB_Log_20250315_1200.trn'
WITH COMPRESSION;
-- Informationen über Log-Backups (Größe, letztes Backup)
SELECT
database_name,
backup_start_date,
backup_size / 1024 / 1024 AS SizeMB,
DATEDIFF(minute, backup_start_date, backup_finish_date) AS DurationMin
FROM msdb.dbo.backupset
WHERE type = 'L' -- L = Log-Backup
AND database_name = 'MeineDB'
ORDER BY backup_start_date DESC;
💡 Tipp: Verwenden Sie
BACKUP LOG WITH COMPRESSION, um Speicherplatz zu sparen (die Komprimierungsrate ist bei Logs allerdings geringer als bei Datenbackups). Achten Sie auf ausreichend Platz auf dem Backup-Ziel.
🔄 Hochverfügbarkeit und das Transaktionslog
HADR
Alle Synchronisationslösungen nutzen das Transaktionslog als Grundlage:
- Log-Shipping: Log-Backups werden regelmäßig auf einen Secondary kopiert und dort wiederhergestellt.
- Always On Availability Groups: Das Log wird synchron oder asynchron direkt an die sekundären Replikate gesendet.
- Spiegelung (veraltet): Ähnliches Prinzip.
-- Bei Always On: Log-Sendungsstatus prüfen
SELECT
ag.name,
ars.role_desc,
drs.synchronization_state_desc,
drs.log_send_queue_size,
drs.redo_queue_size
FROM sys.dm_hadr_database_replica_states drs
JOIN sys.availability_replicas ar ON drs.replica_id = ar.replica_id
JOIN sys.availability_groups ag ON ar.group_id = ag.group_id
JOIN sys.availability_replicas ars ON drs.replica_id = ars.replica_id;
📉 Transaktionslog verkleinern (Shrink) – Dos and Don‘ts
WARTUNG
Ein plötzlich stark gewachsenes Log kann aus diversen Gründen auftreten (keine Log-Backups, sehr große Transaktion, Replikationsproblem). Das Verkleinern (
DBCC SHRINKFILE) ist möglich, aber nicht immer ratsam.
Wann Shrink sinnvoll ist:
- Nach einmaligen riesigen Log-Einträgen (z. B. nächtlicher Batch-Job).
- Nachdem Sie das Recovery Model von FULL auf SIMPLE geändert haben und das Log physisch verkleinern möchten.
- Bei akutem Platzmangel auf dem Laufwerk.
- Regelmäßige Shrink-Jobs – das fragmentiert das Log und erzeugt tausende VLFs.
- Wenn das Log normalwüchsig ist (z. B. regelmäßige Log-Backups).
- In Always On-Umgebungen ohne gründliche Analyse.
-- Log-Datei verkleinern (nur nach Log-Backup und Checkpoint)
USE [MeineDB];
CHECKPOINT; -- Dirty Pages schreiben
DBCC SHRINKFILE (N'MeineDB_log', 'ZIELGRÖSSE_IN_MB');
-- Um den aktuellen Log-Speicherplatz zu sehen:
SELECT
name,
size * 8 / 1024 AS CurrentSizeMB,
CAST(size * 8 / 1024.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS INT) * 8 / 1024.0 AS DECIMAL(10,2)) AS FreeSpaceMB
FROM sys.database_files
WHERE type_desc = 'LOG';
🚨 Warnung: Ein Shrink des Logs mit anschließendem automatischen Wachstum (wieder in kleinen Schritten) erzeugt sehr viele VLFs, was die Performance beeinträchtigt. Daher: Lieber auf eine angemessene Initialgröße setzen und Shrink nur in Ausnahmefällen.
⚠️ Häufige Log-Probleme & Fehlerbehandlung
TROUBLESHOOTING
- „The transaction log for database … is full“ → Meist keine Log-Backups bei FULL Recovery Model. Lösung: Log-Backup durchführen oder Recovery Model auf SIMPLE wechseln (nur temporär).
- Log wächst unkontrolliert, obwohl Log-Backups laufen → Ursache kann eine lange aktive Transaktion sein (
DBCC OPENTRAN). Finden Sie die Session und beenden Sie sie (KILL). - Sehr viele VLFs (tausende) → Dann ist die Log-Datei zu oft in kleinen Schritten gewachsen. Lösung: Log auf eine sinnvolle Größe setzen (z. B. 2 GB), Shrink ausführen, dann wieder vergrößern (diesmal in einem Schritt).
- „Log shipping secondary stuck“ → Das Log kann nicht abgeschnitten werden, weil der Secondary nicht wiederherstellt. Prüfen Sie die Log-Shipping-Jobs.
- Lange Laufzeit von Log-Backups → Sehr viele VLFs oder fragmentiertes Log. Die VLF-Anzahl reduzieren (siehe oben).
-- Aktive Transaktionen finden, die das Log blockieren
DBCC OPENTRAN;
-- Detailliertere Information über lang laufende Transaktionen
SELECT
st.session_id,
st.text,
tat.transaction_begin_time,
DATEDIFF(minute, tat.transaction_begin_time, GETDATE()) AS RunningMinutes
FROM sys.dm_tran_active_transactions tat
JOIN sys.dm_tran_session_transactions tst ON tat.transaction_id = tst.transaction_id
JOIN sys.dm_exec_sessions s ON tst.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(s.most_recent_sql_handle) st
WHERE tat.transaction_state = 2; -- aktive Transaktion
💡 Praxistipp: Bei einem vollen Log können Sie schnell Platz schaffen, indem Sie das Recovery Model auf SIMPLE setzen (erfordert keine Log-Backups) und dann einen Checkpoint durchführen. Danach das Log verkleinern. Aber denken Sie daran: Danach wieder FULL (falls benötigt) und ein volles Backup starten.
📊 Log-Überwachung – DMVs und Performance-Counter
MONITORING
Um frühzeitig zu erkennen, wenn das Log übermäßig wächst oder Probleme auftreten, helfen folgende DMVs und Systemfunktionen:
-- Aktuelle Größe und Verwendung des Logs
SELECT
DB_NAME(database_id) AS DBName,
CAST(total_log_size_mb AS DECIMAL(10,2)) AS TotalLogSizeMB,
CAST(used_log_space_mb AS DECIMAL(10,2)) AS UsedLogMB,
CAST(used_log_space_in_percent AS DECIMAL(5,2)) AS UsedPercent
FROM sys.dm_db_log_space_usage;
-- Log-Wachstums-Ereignisse im Standardprotokoll
SELECT TOP 10 log_time, [text], database_name
FROM sys.fn_xe_file_target_read_file(N'System_Health*.xel', NULL, NULL, NULL)
WHERE [text] LIKE '%log%grow%'
ORDER BY log_time DESC;
💡 Alerts einrichten: Benachrichtigen Sie sich, wenn der verwendete Log-Platz 70 % überschreitet. So können Sie eingreifen, bevor das Log vollständig läuft.
✅ Best Practices – So bleibt Ihr Log gesund
PRAXIS
- Wählen Sie das passende Recovery Model: Für Produktion → FULL, für Test/Sandbox → SIMPLE.
- Log-Backups regelmäßig durchführen (bei FULL Modell) – sonst wächst das Log endlos.
- Initiale Log-Größe großzügig wählen (z. B. 1 GB bis 5 GB) – vermeidet häufige Autogrowth-Ereignisse.
- Autogrowth in MB festlegen (z. B. 512 MB), nicht in Prozent – verhindert VLF-Fragmentierung.
- VLFs regelmäßig überwachen – mehr als einige tausend sind problematisch.
- Keine regelmäßigen Log-Shrinks – sie ruinieren die Performance und zersplittern das Log.
- Überwachen Sie lang laufende Transaktionen – sie verhindern das Abschneiden des Logs.
- Backups testen – führen Sie regelmäßig Proberestores durch, inklusive Log-Backups.
- Log auf separatem Laufwerk (oder zumindest nicht mit Datenbankdateien zusammen) – reduziert I/O-Konflikte und ermöglicht Point-in-Time-Recovery auch bei defekter Datendatei.
🆘 Notfall – Das Log ist voll (fehler 9002)
KRITISCH
Sollte die Datenbank aufgrund eines vollen Transaktionslogs keine weiteren Änderungen zulassen, gehen Sie wie folgt vor:
- 1. Prüfen Sie den Recovery Model:
SELECT name, recovery_model_desc FROM sys.databases. - 2. Bei FULL: Führen Sie sofort ein Log-Backup durch (mit ausreichend Platz auf dem Ziel).
- 3. Falls kein Platz für ein Log-Backup vorhanden ist, wechseln Sie temporär zu SIMPLE (
ALTER DATABASE ... SET RECOVERY SIMPLE). - 4. Führen Sie einen Checkpoint durch:
CHECKPOINT. - 5. Verkleinern Sie das Log:
DBCC SHRINKFILE (N'..._log', 2048)(wenn nötig). - 6. Stellen Sie das Recovery Model wieder auf FULL zurück (falls benötigt) und machen Sie ein volles Backup.
🚨 Wichtig: Der Wechsel zu SIMPLE zerstört die Log-Kette – Point-in-Time-Wiederherstellung ist danach nicht mehr möglich, bis ein neues volles Backup erstellt wurde. Nur im Notfall anwenden!