Quick Answer
LOGBUFFER waits occur when SQL Server cannot find available space in the transaction log buffer to write new log records. This happens when log writes to disk are slower than log generation, typically indicating storage I/O bottlenecks on the transaction log drive. High LOGBUFFER waits usually signal inadequate log disk performance or excessive transaction volume.
Root Cause Analysis
The transaction log buffer is a memory structure that temporarily holds log records before they are written to the physical log file. When a transaction commits or the buffer becomes full, the Log Writer thread flushes these records to disk. LOGBUFFER waits occur when worker threads need to write log records but the circular log buffer lacks available space.
This bottleneck manifests when log generation rate exceeds the Log Writer's ability to flush buffers to storage. The Log Writer operates on a background thread that continuously writes dirty log pages from memory to the transaction log file. If storage cannot keep pace with the flush requests, the log buffer fills completely.
SQL Server 2016 introduced improvements to log writer efficiency through multiple log writer threads for high-concurrency workloads. SQL Server 2019 added Accelerated Database Recovery (ADR), which changes log buffer dynamics by reducing the need to read log records during recovery operations. SQL Server 2022 enhanced this further with optimized log writer algorithms for cloud storage scenarios.
The scheduler quantum affects LOGBUFFER waits because transactions holding log buffer space may be preempted before completing their writes. Buffer pool pressure can exacerbate this when memory pressure forces more frequent checkpoints, increasing log activity. Lock manager escalations also generate additional log records during high-concurrency operations.
AutoDBA checks transaction log file placement, sizing recommendations, and storage performance metrics across your entire SQL Server instance in 60 seconds. Download the free diagnostic script and see what else needs attention.
Diagnostic Queries
-- Check current log buffer waits and duration
SELECT
wait_type,
waiting_tasks_count,
wait_time_ms,
max_wait_time_ms,
signal_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE wait_type = 'LOGBUFFER'
AND waiting_tasks_count > 0;
-- Identify databases with highest log generation rates
-- Performance counters are keyed by instance_name (database name), not database_id
SELECT
pc1.instance_name AS database_name,
log_bytes.cntr_value / 1024.0 / 1024.0 AS log_mb_flushed,
flush_wait.cntr_value AS log_flush_wait_time_ms,
flushes.cntr_value AS log_flushes,
flush_wait.cntr_value / NULLIF(flushes.cntr_value, 0) AS avg_flush_wait_ms
FROM sys.dm_os_performance_counters pc1
CROSS APPLY (
SELECT cntr_value
FROM sys.dm_os_performance_counters pc2
WHERE pc2.counter_name = 'Log Bytes Flushed/sec'
AND pc2.instance_name = pc1.instance_name
) log_bytes
CROSS APPLY (
SELECT cntr_value
FROM sys.dm_os_performance_counters pc3
WHERE pc3.counter_name = 'Log Flush Wait Time'
AND pc3.instance_name = pc1.instance_name
) flush_wait
CROSS APPLY (
SELECT cntr_value
FROM sys.dm_os_performance_counters pc4
WHERE pc4.counter_name = 'Log Flushes/sec'
AND pc4.instance_name = pc1.instance_name
) flushes
WHERE pc1.counter_name = 'Log Bytes Flushed/sec'
AND pc1.instance_name <> '_Total'
ORDER BY log_mb_flushed DESC;
-- Check log file I/O latency by database
SELECT
DB_NAME(vfs.database_id) as database_name,
vfs.io_stall_write_ms / NULLIF(vfs.num_of_writes, 0) as avg_write_latency_ms,
vfs.num_of_writes,
vfs.num_of_bytes_written / 1024.0 / 1024.0 as mb_written,
mf.physical_name
FROM sys.dm_io_virtual_file_stats(NULL, NULL) vfs
JOIN sys.master_files mf ON vfs.database_id = mf.database_id
AND vfs.file_id = mf.file_id
WHERE mf.type = 1 -- Log files only
ORDER BY avg_write_latency_ms DESC;
-- Find sessions currently waiting on LOGBUFFER
SELECT
s.session_id,
s.login_name,
s.program_name,
r.wait_type,
r.wait_time,
r.command,
t.text as current_statement
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 r.wait_type = 'LOGBUFFER';
-- Check log buffer size and usage
SELECT
counter_name,
cntr_value,
cntr_type
FROM sys.dm_os_performance_counters
WHERE counter_name IN (
'Log Pool Cache Misses/sec',
'Log Pool Disk Reads/sec',
'Log Pool Requests/sec'
)
AND object_name LIKE '%Buffer Manager%';
Fix Scripts
Move log files to faster storage
-- Generate ALTER DATABASE statements to move log files to SSD storage
-- Review and execute these statements during maintenance window
SELECT
'ALTER DATABASE [' + db.name + '] MODIFY FILE (NAME = ''' + mf.name + ''', FILENAME = ''E:\FastLogs\' + mf.name + '.ldf'');' as move_statement
FROM sys.databases db
JOIN sys.master_files mf ON db.database_id = mf.database_id
WHERE mf.type = 1 -- Log files
AND db.database_id > 4 -- Exclude system databases
ORDER BY db.name;
-- After moving files, restart SQL Server service to complete the move
Test this on development environments first. Plan for service downtime during the file move operation.
Increase log file size to reduce auto-growth events
-- Pre-size log files based on current usage patterns
-- This reduces auto-growth overhead during peak periods
DECLARE @sql NVARCHAR(MAX) = '';
SELECT @sql = @sql +
'ALTER DATABASE [' + db.name + '] MODIFY FILE (NAME = ''' + mf.name + ''', SIZE = ' +
CAST(CEILING(mf.size * 8.0 / 1024 * 1.5) AS VARCHAR(20)) + 'MB);' + CHAR(13)
FROM sys.databases db
JOIN sys.master_files mf ON db.database_id = mf.database_id
WHERE mf.type = 1 -- Log files
AND db.database_id > 4
AND mf.growth > 0; -- Only resize files that can grow
PRINT @sql;
-- Review the output and execute manually after validation
This increases log file sizes by 50% to reduce auto-growth frequency. Monitor disk space before implementation.
Enable Accelerated Database Recovery for SQL Server 2019+
-- Enable ADR to reduce log scan requirements during recovery
-- This can indirectly help with log buffer pressure
SELECT
'ALTER DATABASE [' + name + '] SET ACCELERATED_DATABASE_RECOVERY = ON;' as enable_adr
FROM sys.databases
WHERE database_id > 4 -- Skip system databases
AND is_read_only = 0
AND state = 0; -- Online databases only
-- Monitor ADR overhead after enabling
SELECT
database_id,
DB_NAME(database_id) as database_name,
persistent_version_store_size_kb / 1024.0 as pvs_size_mb
FROM sys.dm_tran_persistent_version_store_stats
WHERE persistent_version_store_size_kb > 0;
ADR introduces persistent version store overhead. Monitor PVS growth after enabling. Not recommended for databases with high update workloads without sufficient storage.
Optimize checkpoint frequency for heavily updated databases
-- Adjust recovery interval to reduce checkpoint frequency
-- This can reduce log buffer pressure from checkpoint operations
EXEC sp_configure 'recovery interval (min)', 5; -- Increase from default 0 (1 minute)
RECONFIGURE WITH OVERRIDE;
-- Verify current checkpoint behavior per database
SELECT
database_id,
DB_NAME(database_id) as database_name,
last_log_backup_lsn,
recovery_model_desc
FROM sys.databases
WHERE database_id > 4
ORDER BY database_id;
Longer recovery intervals reduce checkpoint frequency but increase crash recovery time. Balance checkpoint overhead against recovery time requirements.
AutoDBA generates fix scripts like these automatically, with impact estimates and rollback SQL included.
Prevention
Configure transaction log files on dedicated high-performance storage with low latency, ideally NVMe SSDs with direct-attached storage or high-IOPS SAN LUNs. Separate log files from data files across different physical drives to eliminate I/O contention.
Pre-size log files appropriately based on peak transaction volumes to minimize auto-growth events. Set log file growth to reasonable fixed MB values rather than percentage-based growth to maintain consistent performance during expansion operations.
Monitor log generation rates using sys.dm_os_performance_counters and establish baselines for normal operation. Create alerts when log flush wait times exceed 10-15ms consistently, indicating storage bottlenecks developing.
For SQL Server 2019 and later, evaluate Accelerated Database Recovery for databases with frequent long-running transactions, as ADR reduces log scan requirements during recovery operations. However, monitor persistent version store growth carefully.
Implement proper transaction design patterns including minimizing transaction duration, avoiding unnecessary explicit transactions around single statements, and batching large operations into smaller chunks to reduce log buffer pressure during bulk operations.
Consider log shipping or Always On Availability Groups configuration impacts, as secondary replica log hardening requirements can increase log buffer retention time if network latency or secondary storage performance becomes a bottleneck.
Need hands-on help?
Dealing with persistent logbuffer issues across your environment? Samix Technology provides hands-on SQL Server performance consulting with 15+ years of production DBA experience.