SUBMIT A FILE TYPE CONTACT US SUPPORT ABOUT US

What Is an LDF File? The SQL Server Log That Still Contains Your Deleted Rows

LDF files are SQL Server logs, and they still contain the values of rows you deleted. Jump to your question below, or work through it in order.

35 min read Updated October 2026 Checked against sources and tests

What Is an LDF File? The SQL Server transaction log, and two other types share the ending

Short answer

An LDF file is the transaction log of a SQL Server database. It records every change to the data in order, so SQL Server can undo a failed change and recover after a crash. Two other file types, a LaserDisc capture and a Lingoes dictionary source, share the ending.

We read one 1 MB SQL Server log and matched all 726 of its records to SQL Server’s own dump. Then we damaged it in 50 ways. Our script printed no message on 12 copies, and 10 of them read differently from the original.

To open an LDF file, go to the opening steps. To check one, go to the six steps. If an LDF file causes an error, begin with the eight causes.

An LDF file is the transaction log of a Microsoft SQL Server database. It records every change to the data in order, so the server can undo a failed change and recover after a crash. SQL Server writes it beside the MDF data file.

Open the data folder of a SQL Server instance and you find two files for every database. A database named shop has shop.mdf for the data and shop_log.ldf for the changes. Every LDF file in that folder belongs to one database. On Linux the default folder is /var/opt/mssql/data.

Microsoft Learn lists .mdf, .ndf and .ldf as the recommended extensions for primary data files, secondary data files and transaction logs. They are recommended names and not rules. A database needs at least one log file.

The transaction log guide says LDF files record all transactions and the changes that every one made to the database. Every record has a log sequence number, or LSN. An LDF file lets SQL Server roll back one transaction and recover the database at startup.

FileInfo lists three types for the .ldf ending. The first is the SQL Server transaction log. The second is a source file for the Lingoes dictionary program, and the third is a LaserDisc capture compressed with FLAC. This page studies the SQL Server type and covers the other two briefly.

Where our LDF file comes from

We found one SQL Server log that we could study. It is a test file from an open source log reader, with 1,048,576 bytes. A code comment in that project says SQL Server 2022 wrote it. We did not make the file, and we did not install SQL Server.

The project ships a dump of the same log, which SQL Server printed with its fn_dblog function. We matched all 726 of our records to that dump by LSN, operation and transaction. Every record agreed, so we trust what our readers found.

Then we damaged the file in 50 ways, one change at a time. Two readers of our own handled the 50 LDF files, and the file command named them. We list the limits in the format part.

LDF file facts at a glance

Quick facts about LDF files
Property Value
Meaning The SQL Server transaction log. FileInfo lists two other types for .ldf, a Lingoes dictionary source and a LaserDisc capture.
Made by SQL Server, when you create a database and every time the database changes.
Format Binary. Our LDF file has an 8 KB file header page, four virtual log files and 40 blocks that contain 726 records.
Start The bytes 01 0F 00 00 08 02 00 00 in our LDF file. The file command calls it data.
Pairs with An MDF file for the data. Larger databases can add NDF files and more log files.
Opens with SQL Server itself. Two Windows viewers read LDF files from outside.
MIME type None found for the SQL Server type in the part of the IANA list we could read.
Size in our set 1,048,576 bytes, of which 24.6 percent was in use.
Our tests One log, 50 damaged LDF files and two readers of our own, on Linux.

Wrong page? Look at the MDF file for the data file, the LDIF file for a directory exchange file or the DAT file for unknown data.

What Is Inside an LDF File? A file header, four virtual logs and 40 blocks of records

Our 1 MB LDF file is built from an 8 KB file header page, four virtual log files and 40 blocks of records. Two virtual logs are in use, and two are filled with C0 bytes. Records start at byte 72 of a block.

The figure shows our LDF file to scale. SQL Server splits the log into virtual log files, or VLFs, and Microsoft on virtual log files says you cannot set their size or number. Our LDF file has four.

How our 1 MB SQL Server LDF file is built. An 8 KB file header page comes first, then four virtual log files of 248, 248, 248 and 272 KB. The first two are in use, with sequence numbers 42 and 43, and the last two are unused and filled with C0 bytes. The first VLF contains 37 blocks and 714 records. A block has a header, the records, free space and a slot array that points to the start of every record.
Sizes and counts are from our 1 MB test file. Unused space is filled with C0 bytes, and the last VLF is larger than the other three.

The first two VLFs are in use, and their sequence numbers are 42 and 43. The other two have sequence 0 and contain only C0 bytes. All four VLF header pages add up to 32,768 bytes. The blocks use 258,048 bytes, which is 24.6 percent of the file.

The file header page

The first 8,192 bytes of an LDF file are the file header page. Our LDF file starts with 01 0F 00 00 08 02 00 00. We use the first two bytes as a signature, and we do not know what every other field means. The fields we read are enough to find every record.

The first 48 bytes of our LDF file
00000000: 010f 0000 0802 0000 0000 0000 0000 0000  ................
00000010: 0000 0000 0000 0200 6300 0000 2014 d019  ........c... ...
00000020: 0000 0000 0200 0000 0000 0000 0000 0000  ................

Virtual log files and their headers

Every VLF in an LDF file starts with its own 8 KB header page. We read the marker byte AB first, then one byte of parity bits, then the sequence number at byte 4. The size is at byte 16 and the start offset is at byte 24. Our script checks all five.

The first VLF header, at offset 8192
00002000: ab40 0500 2a00 0000 0000 0000 0100 0000  .@..*...........
00002010: 00e0 0300 0000 0000 0020 0000 0000 0000  ......... ......

VLF 1 has marker AB, parity 40 and sequence 42. Its size is 0003E000 in little endian, which is 253,952 bytes. Its start offset is 8,192. A VLF that is not in use has sequence 0 and a body of C0 bytes.

Blocks and records

The body of a used VLF is a row of blocks. Ours has 40 in all, 33 of 4,096 bytes and the rest from 8 to 40 KB. Every block size is a multiple of 512 bytes. A block starts with a header, and the first record begins at byte 72.

The first block of VLF 1, at offset 16384
00004000: 5000 0200 b801 0010 0300 0000 2a00 0000  P...........*...
00004010: 1000 0000 0100 0000 d5a4 d9b9 0000 0000  ................

The header gives the record count (2), the end of the slot array (440), the block size (4,096), the VLF sequence (42) and the block number. The slot array is at the end of the block and lists where every record starts.

One more detail matters. The first byte of every 512 byte sector in a block is parity bits, and SQL Server saves the original byte at the end of the block. A reader must put those bytes back before it reads a record.

We read this layout from one file. The field positions come from our LDF file and from the code of three open source readers. They are not a Microsoft specification, and SQL Server can write more than we saw. We did not test other versions.

Which Types of LDF File Exist? Three types share the ending, and the first bytes separate them

Three file types use the .ldf ending. The first bytes separate them. A SQL Server log starts with 01 0F 00 00, a LaserDisc capture starts with the letters fLaC or OggS, and a Lingoes source file is text.

LDF files share an ending with programs that never met. FileInfo lists the three types in the figure. It scores the SQL Server log 4.2 out of 5 from 17 votes. The other two types have 3 votes and 2 votes, so we do not use the scores to rank them.

Three file types that use the LDF ending and how to separate them. A SQL Server transaction log starts with the bytes 01 0F 00 00, and the file command calls it data. A LaserDisc capture is FLAC audio and starts with the letters fLaC, or OggS when wrapped in Ogg. A Lingoes dictionary source file is text and we tested none.
The first bytes are the quickest test. Our SQL Server file is the log of a test database, and the FLAC file is one we made ourselves.

The SQL Server transaction log

This is the type of LDF file that the rest of the page studies. The file command 5.45 printed only data for our LDF file, and it never named SQL Server. Do not count on file to find a SQL Server LDF file.

The LaserDisc capture

FileInfo describes an LDF file made by ld-compress, a tool from the LaserDisc decoding project. It compresses a raw capture of the laser signal with FLAC. The decoder ld-decode on Linux reads it, according to the project pages we found.

We found no capture to test. We made two small files with FLAC and with Ogg wrapped FLAC to see what file says. The first bytes were 66 4C 61 43, which spell fLaC, and 4F 67 67 53, which spell OggS.

The file command named them FLAC audio bitstream data and Ogg data, FLAC audio. Those are files we made, so the tool itself can wrap its output differently. RFC 9639 on FLAC defines the FLAC format, and audio/flac is a registered media type.

The Lingoes dictionary source

FileInfo calls this a source file in text form. It lists the title of a dictionary, the terms and the definitions, and the program compiles it into a dictionary. We found no sample and could not read the format page of the project, so we tested nothing.

Open the file in a text editor to see which type of LDF file you have. Readable words with titles and definitions point to the Lingoes source. A jumble of symbols that starts with 01 0F points to the SQL Server log.

SQL Server log Starts with 01 0F. Beside an MDF file in a data folder.
LaserDisc capture Starts with fLaC or OggS. Made by ld-compress.
Lingoes source Readable text with titles, terms and definitions.
Not sure Read the first bytes before you open it with anything.

Not sure the file is an LDF file at all? Check it with our script.

What Does One SQL Server LDF File Contain? 726 records, 35 transactions and a deleted name that stayed

Our SQL Server LDF file has 726 records in 40 blocks, and they use 24.6 percent of its 1 MB. COUNT_DELTA is the most common operation. 35 transactions began and 34 of them committed. One rolled back, and its change is still readable.

We read the LDF file with our script and with a second reader, and we matched every record to SQL Server’s own dump. The figure shows where the bytes go, which operations dominate and what the transactions did. It describes one LDF file and not all LDF files.

726 records read and matched
35 transactions began
34 transactions committed
1 transaction rolled back
What one 1 MB SQL Server log contains. 726 records in 40 blocks use 258,048 bytes, which is 24.6 percent of the file, and the rest is unused fill. COUNT_DELTA is the most common record with 233, then INSERT_ROWS with 137 and SET_BITS with 61. 35 transactions began, 34 committed and 1 rolled back. A deleted name and a rolled back change are still readable in the records.
Counts are from the 726 records we read and matched, record by record, to SQL Server’s own dump of the same log.

The 25 operation types

Our LDF file has 25 operation types. Seven of them make up 592 of the 726 records, and the other 18 types make up 134. SQL Server prints the names with the prefix LOP_, so INSERT_ROWS appears as LOP_INSERT_ROWS in its dump.

We did not study what every operation does. The names that explain themselves are INSERT_ROWS, DELETE_ROWS, BEGIN_XACT, COMMIT_XACT and ABORT_XACT. Records in our LDF file are small. The median is 128 bytes, and the largest is 5,208.

The transactions in our LDF file

Our LDF file shows 35 begun transactions. 34 committed and 1 aborted, which is the rolled back change. Their names include ldffixture, CREATE TABLE, INSERT, UPDATE, DELETE and undone. All the begin times fall within about a third of a second on 4 October 2026.

What the records still contain

We searched the records for the values in the test table. The name Ali Khan is readable in two records, the insert and the delete. A deleted row is still in an LDF file, with its values, after the row left the table.

The rolled back change wrote the word Nobody into one MODIFY_ROW record, and the word is still there. The names Sara and Ahmed appear in four records and one record. The two unused VLFs contain only C0 bytes, so nothing hides in them.

Old rows stay A deleted row is readable in its delete record.
Undone changes stay The rolled back change is still in a record.
A quarter is used 258,048 of 1,048,576 bytes contain blocks. The rest is fill.
One dump agrees All 726 records match SQL Server’s own dump.

Read the study with care. It shows one log of one small test database with a few changes. A busy server writes different records. We read no log from SQL Server 2019 or older, and we did not use a Windows system.

What Happens When an LDF File Is Damaged? 50 broken copies, two readers and 10 silent differences

We damaged one LDF file in 50 ways and read every copy with two readers of our own. Our script printed no message on 12 copies, and 10 of them read differently from the original. A salvage scan read all 726 records on 33 copies and printed nothing.

We changed one thing at a time and sorted the 50 LDF files into seven groups. They cover cuts, the file header, VLF headers, block headers, sector bytes, record bytes and extra bytes. Copy numbers match the rows of the figure.

A grid of 50 damaged copies of one SQL Server LDF file and three readers. The file command says data for 49 copies and empty for one. Our 69 line script read all 726 records on 19 copies, printed a message for 38 and stayed silent on 12. Ten copies read differently with no message. Our salvage scan read all 726 records on 33 copies and prints no messages at all.
Cells show the number of records found. Green is the same as the intact file, blue is the same with a message, amber is different with no message and red is different with a message.

Green means the reader found the same records as in the original, and nothing was printed. Blue is the same records with a message. Amber is other records with no message, and red is other records with a message. The file column shows what the file command said.

The file command cannot see damage

The file command printed data for 49 copies and empty for the empty one. It gave the same answer for a healthy log and for a log with a changed name inside. It is no check of a SQL Server LDF file.

Our script sees structure and misses content

Our script read all 726 records on 19 copies. It printed a message on 38 copies and stayed silent on 12. Two of the silent copies, 12 and 14, read correctly. The other ten read differently with no message at all.

Those ten are copies 6, 30, 35, 37 to 42 and 46. Copy 6 is cut after VLF 1, so the script reads 714 records and finds nothing wrong. The other nine changed bytes inside a block, and the script checks the structure and not the values.

Copy 38 changes the name Ali to Bob inside one record. Both of our readers read all 726 records with no message. We found no check in our script or our salvage scan that could see it.

A message does not mean lost records

The script printed a message on eight copies that still read all 726 records. They are copies 8 to 11, 13, 47, 48 and 50. Those copies have a damaged file header page, a missing last byte or extra bytes, and the blocks themselves are fine.

The reverse is worse. Copies 16 to 19 changed one byte of the first VLF header, and the script read only 12 records. Its message names an offset where the LDF file looks damaged or unused. The message shows that something is wrong, and it does not say that most records are lost.

A salvage scan finds more and says nothing

The salvage scan ignores the VLF headers. It checks every 512 byte step of the file for a block that passes its own checks. It read all 726 records on 33 copies and found more records than the script on 23 copies. It never found fewer.

Over the 50 LDF files the script lost 17,061 records and the salvage scan lost 3,511. The scan prints no message, though. On 28 copies its answer is different from the original, and nothing says so. A silent scan of LDF files trades a loud failure for a quiet one.

What the groups show

Results by group of damaged LDF files
Group What we found
A. Cut short (1 to 8) The script refused copies 1 to 5 and read 714 records on copies 6 and 7. The salvage scan found 726 records in copy 7. The empty copy is the only one that file called empty.
B. File header page (9 to 14) Both readers found all 726 records on all six copies. Four of them printed a message. Copies 12 and 14 changed bytes the script never reads.
C. VLF headers (15 to 22) The script kept 714 records or fewer on all eight copies and flagged every one. The salvage scan read all 726 records on every one of the eight.
D. Block headers (23 to 30) The script read 725 records or fewer on seven copies and flagged every one. Copy 30 changed the slot number of the first record, and the script read 726 records with other numbers and printed nothing.
E. Sector bytes (31 to 36) A flipped parity bit stopped the script at that block. Copy 35 changed one saved byte, and both readers read 726 records, one of them changed, with no message.
F. Record bytes and block order (37 to 46) Seven copies changed a record, and neither reader printed a message. Copies 43 to 45 changed a slot offset or swapped blocks, and the script flagged them.
G. Extra bytes (47 to 50) Both readers found all 726 records on copies 47, 48 and 50, and the script printed a message. Copy 49 had 512 zero bytes in front, and only the salvage scan read the LDF file.

Read the grid with care. Green cells mean only that a reader found the same records as in the original file. We opened no copy in SQL Server, and SQL Server can check more than our readers do. Every test changed one thing in one file.

What Does Our Expert Say About LDF Files? A note from Neeraj Singh on treating the log like the data

Treat an LDF file like the database. It contains the values of the rows that changed, and a deleted row stays readable in it. Share LDF files only with people you would trust with the data, and keep them safe the way you keep MDF files.

Neeraj Singh

Expert insight

An LDF file looks like a file you can ignore, but it contains the old and new values of your rows. In our test, a deleted name and a rolled back change were still readable in the file. Treat every LDF file like the database itself, and never send one to a stranger.

Neeraj Singh Manager, Tech Support & Operations 19+ years fixing Windows and system errors

Why a quiet log is the risky one

Nobody opens LDF files, so nobody thinks about them. A backup of the MDF file alone looks like the entire database, yet LDF files can contain rows that left the table. In our LDF file the deleted name was in two records.

Damage hides in the same way. Ten of our 50 copies read differently, and our script said nothing. A reader that finds no problem in an LDF file has found none in the parts it checks, and that is all it proves.

Keep the original. Copy an LDF file before you read it, and write down its SHA256 hash. The hash shows which file you received, and it shows if a transfer changed it later.

How Do You Open an LDF File? SQL Server reads it, and two Windows viewers show it

SQL Server opens an LDF file for you when the database comes online, and you rarely open one by hand. To read the records from outside, use the fn_dblog function in SQL Server or a viewer that reads the MDF and LDF files together. A text editor shows only symbols.

LDF files are binary, so a text editor shows symbols and not words. Do not save it after you open one. We tested our own readers on Linux and read both pages of the two Windows tools below. We installed neither tool.

In SQL Server

SQL Server opens LDF files when the database goes online. To use a database that came as an MDF file and an LDF file, attach both. Microsoft on where attach looks for a log says it uses the old location unless you name a new one.

Attach a database with its log
CREATE DATABASE shop
ON (FILENAME = '/var/opt/mssql/data/shop.mdf')
LOG ON (FILENAME = '/var/opt/mssql/data/shop_log.ldf')
FOR ATTACH;

Microsoft’s attach warning also warns against attaching or restoring databases from unknown or untrusted sources. It says to check it with DBCC CHECKDB on a nonproduction server first. Treat any LDF file from a stranger the same way.

The fn_dblog function reads the active log of the current database. Our dump of 726 records came from it. We found no Microsoft page that documents the function, so its columns can change between versions.

Read the active log in SQL Server
SELECT * FROM fn_dblog(NULL, NULL);

Two Windows viewers

These cards link to the two Windows programs that name LDF files on their own pages. Both read the log of a database and not a loose LDF file. Both pages describe a trial with limits, and we read the pages and did not use the programs.

SysTools SQL Log Analyzer

Reads the log of a SQL Server database on Windows

Trial shows 50 records per table

Freeviewer LDF File Viewer

Opens and previews an LDF file on Windows

Demo shows 50 records per table

The SysTools page describes a tool that needs the MDF file and the LDF file together. It does not open backup files that end in .trn. It exports to SQL Server, to scripts or to CSV. Its free version shows 50 records per table and cannot export.

The Freeviewer page describes the same kind of viewer with the same demo limits. We cannot say how either tool treats a damaged LDF file, because we did not use them on our 50 damaged LDF files.

In a hex view and on the command line

Four commands show what an LDF file is without opening it in SQL Server. They hash the file, print its first 16 bytes, name its type and start our 69 line script. The first three work on any Linux or macOS computer.

Four commands to read an LDF file
sha256sum shop_log.ldf
xxd -l 16 shop_log.ldf
file shop_log.ldf
python3 ldf_peek.py shop_log.ldf

The file command printed data for our LDF file. That shows only that it found no known signature. The first bytes 01 0F 00 00 are what point to a SQL Server log.

LaserDisc and Lingoes files

A LaserDisc capture opens in ld-decode on Linux, according to FileInfo and the project pages we found. A Lingoes source file opens in a text editor. We tested neither type, and we found no sample of the Lingoes type.

How the readers did on our 50 damaged LDF files

How every reader did on our 50 damaged LDF files
Reader Result
file 5.45 Printed data for 49 copies and empty for one. It never named SQL Server and never saw a change.
Our script Read all 726 records on 19 copies and printed a message on 38. It stayed silent on 12, and ten of those read differently.
Our salvage scan Read all 726 records on 33 copies and printed no message. It found 726 on 22 copies that match the original and other records on 28.

How Do You Check an LDF File? Six steps, and a 69 line script

Check an LDF file in six steps. Hash it, read its first bytes and name its type. Read the LDF file with a script that checks the headers and the blocks, and compare the counts with SQL Server. No reader proves that the records are the ones SQL Server wrote.

The six steps

  1. Copy the LDF file, write down its SHA256 hash and work on the copy.
  2. Read the first 16 bytes with xxd -l 16 file.ldf. A SQL Server log starts with 01 0F. The letters fLaC or OggS point to a LaserDisc capture.
  3. Check the size. A SQL Server log is a multiple of 8,192 bytes, and ours is 1,048,576.
  4. Use the script below. It reads the headers, finds the blocks and counts the records and the transactions.
  5. Read the last lines of the output. Every problem the script finds gets its own line that starts with PROBLEM.
  6. If you can, compare the counts with fn_dblog on a SQL Server that has the same database.

A 69 line script that reads an LDF file

The Python script below reads an LDF file and does steps 3 to 5 in under a second. It checks the file header page and every VLF header, then reads the blocks and puts the saved sector bytes back. It counts records and prints a line for every problem. It changes no file.

ldf_peek.py
import struct, sys

PAGE, SECTOR, MAXBLOCK = 8192, 512, 61440
NAMES = {1: 'FORMAT_PAGE', 2: 'INSERT_ROWS', 3: 'DELETE_ROWS', 4: 'MODIFY_ROW', 6: 'MODIFY_COLUMNS',
         7: 'SET_BITS', 0x12: 'COUNT_DELTA', 0x80: 'BEGIN_XACT', 0x81: 'COMMIT_XACT',
         0x82: 'ABORT_XACT', 0x8D: 'LOCK_XACT'}

def read_blocks(data, vpos, vsize, seq, parity, ops, problems):
    pos, end, count = vpos + PAGE, vpos + vsize, 0
    while pos + SECTOR <= end:
        n, slot_end, size = struct.unpack_from('<HHH', data, pos + 2)
        bseq, boff = struct.unpack_from('<II', data, pos + 12)
        if not ((data[pos] & 0xC0) == parity and SECTOR <= size <= MAXBLOCK and size % SECTOR == 0
                and pos + size <= end and bseq == seq and boff == (pos - vpos) // SECTOR
                and n > 0 and 24 + 2 * n <= slot_end <= size):
            break
        blk = bytearray(data[pos:pos + size])
        torn = False
        for i in range(1, size // SECTOR):
            torn = torn or (blk[i * SECTOR] & 0xC0) != parity
            blk[i * SECTOR] = blk[size - 1 - i]
        if torn:
            break
        bounds = [struct.unpack_from('<H', blk, slot_end - 2 * k)[0] for k in range(1, n + 1)]
        bounds.append(slot_end - 2 * n)
        bad = False
        for off, nxt in zip(bounds, bounds[1:]):
            if 24 <= off < nxt <= bounds[-1]:
                ops[blk[off + 22]] = ops.get(blk[off + 22], 0) + 1
            else:
                bad = True
        if bad:
            problems.append('impossible record slot in the block at offset %d' % pos)
        count += 1
        pos += size
    if pos < end and set(data[pos:end]) != {0xC0}:
        problems.append('block or unused space is damaged at offset %d' % pos)
    return count

def peek(path):
    data, ops, problems = open(path, 'rb').read(), {}, []
    if len(data) < 2 * PAGE or data[:2] != b'\x01\x0f':
        problems.append('no file header page at the start')
    pos, vlfs = PAGE, []
    while pos + PAGE <= len(data):
        mark, parity, _, seq = struct.unpack_from('<BBHI', data, pos)
        size, start = struct.unpack_from('<qq', data, pos + 16)
        if mark != 0xAB or size < 2 * PAGE or pos + size > len(data) or start != pos:
            problems.append('bad VLF header at offset %d' % pos)
            break
        used = seq != 0 and parity in (0x40, 0x80)
        if not used and set(data[pos + PAGE:pos + size]) != {0xC0}:
            problems.append('VLF at offset %d looks unused but contains data' % pos)
        vlfs.append((pos, size, seq, parity, read_blocks(data, pos, size, seq, parity, ops, problems) if used else None))
        pos += size
    if pos < len(data) and not problems:
        problems.append('%d extra bytes after the last VLF' % (len(data) - pos))
    return vlfs, ops, problems

if __name__ == '__main__':
    vlfs, ops, problems = peek(sys.argv[1])
    for i, (pos, size, seq, parity, blocks) in enumerate(vlfs, 1):
        state = 'unused' if blocks is None else 'sequence %d, %d blocks' % (seq, blocks)
        print('VLF %d at %d, %d bytes, %s' % (i, pos, size, state))
    print('records', sum(ops.values()))
    print('transactions %d begun, %d committed, %d aborted' % (ops.get(0x80, 0), ops.get(0x81, 0), ops.get(0x82, 0)))
    for n, code in sorted(((n, c) for c, n in ops.items()), reverse=True)[:5]:
        print('  %-14s %d' % (NAMES.get(code, '0x%02X' % code), n))
    print('\n'.join('PROBLEM ' + p for p in problems) or 'no problems found')

On our healthy LDF file it prints four VLFs, 726 records and 35 begun transactions. On damaged LDF files it names the point where it stopped. For example, it reads 12 records in copy 17 and says the first VLF looks unused but contains data.

The script on our healthy file
python3 ldf_peek.py shop_log.ldf
VLF 1 at 8192, 253952 bytes, sequence 42, 37 blocks
VLF 2 at 262144, 253952 bytes, sequence 43, 3 blocks
VLF 3 at 516096, 253952 bytes, unused
VLF 4 at 770048, 278528 bytes, unused
records 726
transactions 35 begun, 34 committed, 1 aborted
  COUNT_DELTA    233
  INSERT_ROWS    137
  SET_BITS       61
  MODIFY_ROW     49
  LOCK_XACT      43
no problems found
The script on four damaged LDF files, shortened
python3 ldf_peek.py copy05.ldf
records 0
transactions 0 begun, 0 committed, 0 aborted
PROBLEM bad VLF header at offset 8192

python3 ldf_peek.py copy17.ldf
VLF 1 at 8192, 253952 bytes, unused
records 12
PROBLEM VLF at offset 8192 looks unused but contains data

python3 ldf_peek.py copy33.ldf
VLF 1 at 8192, 253952 bytes, sequence 42, 11 blocks
records 299
PROBLEM block or unused space is damaged at offset 106496

python3 ldf_peek.py copy24.ldf
records 725
PROBLEM impossible record slot in the block at offset 16384

What the script cannot see

The script reads the structure of LDF files and cannot say if the values are the ones SQL Server wrote. It printed no problem for copy 38, where we changed the name Ali to Bob. The same is true for copies 37 to 42 and 46, which changed bytes inside records.

The script on a copy with a changed name
python3 ldf_peek.py copy38.ldf
records 726
no problems found

The script never executes an LDF file, and it does not decode what the records say. It also cannot name the SQL Server version that wrote the file. We wrote it from one file and from the code of three open source readers.

Want the causes of an error? Go to the causes.

Is an LDF File Safe to Share? It contains old rows, so treat it like the database

An LDF file is safe to open in a viewer and unsafe to share. It contains the rows that changed, and a deleted row stayed readable in our LDF file. Do not attach a database from a stranger on a production server, because Microsoft warns against it.

Opening an LDF file in a hex view is not the risk. The risk is what LDF files contain and who gets a copy. We scanned no file for malware, so we cannot say what a downloaded LDF file contains. We can say what LDF files can store.

What an LDF file can contain

Deleted rows Our delete record contains the name Ali Khan, and the row was already gone from the table.
Rolled back changes Our rolled back change wrote the word Nobody into a record, and the record is still there.
Names and values We found the names Sara and Ahmed in the records of a test table.
Times and transaction names Our records contain the begin time and the name of every transaction.

What Microsoft says about attaching

Microsoft’s advice on unknown databases says not to attach or restore databases from unknown or untrusted sources. Such a database can contain malicious code that executes unintended Transact-SQL. It advises you to use DBCC CHECKDB on a nonproduction server and to read its stored procedures first.

The page adds that attach sets some security options off by default. Those include is_trustworthy_on. It is safer to read an untrusted LDF file in a viewer and not to attach it.

Before you share an LDF file

  1. Ask who needs it. A person who asks for the MDF file does not always need the LDF file.
  2. Treat the LDF file as sensitive as the database, and send it only over the channel you use for the data.
  3. Hash the file and send the hash on another channel, so the other side can check it.
  4. Do not assume a backup, a log truncation or a shrink erased old rows from an LDF file. We did not test them.
  5. Look at the LDF file in our script first, to see how many records and transactions it contains.

Use a copy. Work on copies of LDF files, and write down their SHA256 hashes. Keep the original read only, so a reader can never change it.

Why Does Your LDF File Cause an Error? Eight causes, and what to do about every one

LDF files cause errors for eight reasons. The log can be full, missing or on the wrong path. The database can have shut down badly or be read only. The file can be cut, or it can be a different type, and a viewer can lack the MDF file.

The table lists what Microsoft says and what we saw in our 50 damaged LDF files. We did not test the SQL Server errors, because we had no SQL Server. Read every fix as a first step and not as a promise.

Eight causes of LDF file errors
Cause Details and fix
The log is full SQL Server raises error 9002 when the log has no space left. Microsoft on error 9002 lists four causes. The log is not truncated, the disk is full, the size is fixed or autogrow is off, or replication or an availability group cannot finish. Fix: Query log_reuse_wait_desc in sys.databases and act on the value it shows.
The log file is missing Attach looks for the log in its old location. Microsoft on a missing log says it can build a new log only for a read and write database that shut down cleanly with no active log chain. Fix: Keep every detached log file until the attach works, and look for the file before you rebuild.
The database did not shut down cleanly Attach cannot rebuild an LDF file after a crash, because the file is the record SQL Server uses to recover. We did not test this on SQL Server. Fix: Restore a full backup and the log backups made after it, or ask your database administrator.
The database is read only Microsoft says a read only database needs its LDF file at the location stored in the primary file. SQL Server cannot update that location, so it cannot build a new log. Fix: Put the log file back where the primary file expects it.
The file is cut or damaged In our 50 copies, a cut or changed header made our script lose records on 31 of them, and ten copies read differently with no message at all. Fix: Restore from a backup and compare the hash. Do not trust a rebuilt log until you check the database.
It is not a SQL Server log A file that starts with fLaC or OggS is a LaserDisc capture, and a file full of readable words is a Lingoes source. Fix: Read the first bytes, then use the right tool for the type.
The log is not where the database expects it The database stores the log path. A copy that you moved without its path fails to attach. Fix: Name the new path in the LOG ON part of CREATE DATABASE ... FOR ATTACH, as in our attach example.
The viewer needs the MDF file The SysTools page says its tool needs the MDF file and the LDF file together, and it does not open backup files that end in .trn. Fix: Give the viewer both files from the same database, and not a backup.

Fix an LDF file in seven steps

  1. Copy the LDF file and the MDF file, write down their SHA256 hashes and work on the copies.
  2. Read the full error message. Note the error number and the first words.
  3. Read the first 16 bytes with xxd -l 16 file.ldf, and name the type with file file.ldf.
  4. Read the LDF file with the check script. Its problem lines name the point where the file stops making sense.
  5. Check log_reuse_wait_desc in sys.databases if the error says the log is full.
  6. Check that the path in your attach command is the correct path of the file, and that the MDF file belongs to the same database.
  7. If it still fails, restore from a backup and ask a database administrator before you rebuild an LDF file.

We did not test repairs on LDF files from other people. An LDF file that passes our script can still fail in SQL Server, and one that fails in our script can still attach. Only SQL Server knows if its own log is fine.

What to send when you ask for help

If a database administrator or a forum asks about an LDF file, send these lines. They show what was read and where it stopped, and they save rounds of questions.

A message that gets an answer
Subject: LDF file causes an error
File: name, size in bytes and SHA256 hash
First bytes: the output of xxd -l 16 file.ldf
Script: the output of ldf_peek.py
Error: the full text of the message and the command that printed it
Version: the SQL Server version and the operating system
History: what happened to the database before the error

Not an error, but a question about similar files? Go to the versus part.

How Do You Shrink, Move or Rebuild an LDF File? What Microsoft says, since we could not test SQL Server

SQL Server makes an LDF file, and you never convert it. You shrink it, move it or rebuild it. Microsoft says shrinking is not routine maintenance, and a rebuilt log breaks the log backup chain. We tested none of these on SQL Server.

This part reports what Microsoft says about LDF files, because we had no SQL Server to test. We read the pages named in every paragraph and did not change any database. Our own tests cover the file and not the server.

How SQL Server makes an LDF file

Microsoft on CREATE DATABASE says it makes one log file when you name none. Its size is 25 percent of the data files or 512 KB, whichever is larger. The log guide says growth under 64 MB makes 4 VLFs, 64 MB to 1 GB makes 8 and more than 1 GB makes 16.

The same guide says SQL Server 2022 makes one VLF for growth of 64 MB or less. Our LDF file has four. Microsoft on log growth says the default growth is 64 MB from SQL Server 2016, and it advises you to keep FILEGROWTH at or below 1,024 MB.

Shrink an LDF file

A shrink returns free space to the operating system. Microsoft on shrinking says it should not be a regular maintenance task, and it works only when the database is online and at least one VLF is free. AUTO_SHRINK is false by default, and Microsoft does not recommend turning it on.

A log that keeps growing has a reason. Query log_reuse_wait_desc in sys.databases to see it. The values include NOTHING, CHECKPOINT, LOG_BACKUP, ACTIVE_TRANSACTION and REPLICATION. Fix the reason before you shrink.

Ask SQL Server why the log cannot be reused
SELECT name, log_reuse_wait_desc
FROM sys.databases;

Move or copy a database with its log

To move a database, detach it and attach it again with both files. Microsoft on detaching says to keep every detached log file until the attach works without them. Copy the files first and hash them, so you can compare them after the move.

Rebuild a lost log

Microsoft on rebuilding a log says FOR ATTACH_REBUILD_LOG makes a new 1 MB log in the default log location. It needs an orderly shutdown and all the data files, and it works only for read and write databases.

It also breaks the log backup chain, and Microsoft advises a full backup straight after. Rebuilding drops the old LDF file, so it drops every record we studied. Use it only when no better copy exists.

Convert an LDF file to another format

Common conversions and what you get
To Result
CSV or SQL script The SysTools page says its tool exports to SQL Server, to scripts or to CSV. Its trial cannot export. We did not test the export.
MDF file No conversion exists. The MDF file stores the data, and SQL Server writes the log. See what an MDF file is.
Backup file A backup is a separate file that SQL Server writes with a backup command. It is not a converted log.
Video A LaserDisc capture goes through ld-decode on Linux. We tested no capture.

How Does an LDF File Differ From MDF, NDF and BAK Files? One log and four neighbors in the same database

An LDF file records the changes, and an MDF file stores the data. An NDF file adds more data space, and a BAK file is a backup that SQL Server writes on request. Only the LDF file is the transaction log.

People mix these types up because one database uses several of them, and LDF files are the least visible. A database has one MDF file and at least one LDF file, and large ones can have NDF files. Microsoft on database files names the three extensions as recommended.

LDF files next to the files of the same database
Type What it is
LDF The transaction log. It records every change, in order, with an LSN on every record.
MDF The primary data file. It stores the tables and the rows. See our MDF file page.
NDF A secondary data file. It adds space and is optional.
BAK A full or differential backup that SQL Server writes when you ask. It is a copy and not the live database.
TRN A log backup. The SysTools page says its tool does not open this type.

The LDF file and the MDF file go together, and LDF files never work alone. Attach one without the other and SQL Server needs to rebuild or find the missing part, as the attach part explains.

Similar endings cause other mix ups. An MDB file is a Microsoft Access database, covered in our MDB file guide. An LDIF file is a directory exchange file, and our LDIF file guide covers it.

What Is the LDF File Format Made Of? The facts we could check, and where they came from

The SQL Server LDF format is binary, built from an 8 KB file header page, VLFs and blocks of records. The facts below come from Microsoft Learn, FileInfo, the code of three open source readers and our checks of one log and 50 damaged LDF files.

Facts about the LDF file format
Part What we checked
Name SQL Server transaction log. Files end in .ldf. Microsoft calls the extension recommended. (Microsoft Learn)
Other types FileInfo lists a Lingoes dictionary source and a LaserDisc capture compressed with FLAC. (FileInfo)
Container Binary. Our LDF file has an 8 KB file header page, four VLFs and 40 blocks. (our LDF file)
Start The bytes 01 0F 00 00 08 02 00 00. (our LDF file)
VLF header Marker AB, parity bits, sequence at byte 4, size at byte 16 and start offset at byte 24. (our LDF file)
Block A header, records starting at byte 72, free space and a slot array. The first byte of every 512 byte sector is parity bits. (our LDF file)
Records 726 in our LDF file, 25 operation types, and every one has an LSN. (our LDF file, Microsoft Learn)
VLF count Set by SQL Server. Growth under 64 MB gives 4 VLFs, and SQL Server 2022 gives 1. (Microsoft Learn)
Log limits A log can wrap around. If it cannot wrap or grow, SQL Server raises error 9002. (Microsoft Learn)
MIME type None found for the SQL Server type. audio/flac is registered for FLAC. (IANA, RFC 9639)
Our counts One log, 726 records, 50 damaged LDF files and two readers of our own.

About the values we list

Facts about SQL Server come from the Microsoft pages named in the rows. Counts and layout come from our own file. FileInfo is a directory, so we use it for the names of the three types only.

Microsoft does not publish the byte layout of LDF files, as far as we could find. Our layout is what we read from one file, and our readers agree with SQL Server’s own dump on all 726 records.

What we left out

We studied one LDF file from one open source test set, and a code comment says SQL Server 2022 wrote it. We installed no SQL Server and used no Windows system. We read the two viewer pages and used neither tool.

We opened no damaged LDF file in SQL Server, so we cannot say what SQL Server does with them. SQL Server can check more than our readers do, and it can also be less forgiving.

We found no Lingoes file and no LaserDisc capture from the tool itself. The FLAC files we made are not captures from that tool. We read the IANA list only in part, and it showed no entry for the SQL Server type.

Sources checked

For the log, VLFs and error 9002, see the transaction log guide and the error 9002 page. For file names, see database files and filegroups. For attach, see detach and attach and CREATE DATABASE.

For shrinking and growth, see managing the log size and the catalog view reference. For the three types, see the FileInfo page on LDF files. For the product, see Microsoft SQL Server on Wikipedia.

For FLAC, see the FLAC specification. For media types, see the IANA list. The two Windows tools are on the SysTools page and the Freeviewer page. Every count came from files and scripts in our research folder.

Frequently Asked Questions About LDF Files

What is an LDF file?

An LDF file is the transaction log of a Microsoft SQL Server database. It records every change in order, and every record has a log sequence number. SQL Server uses it to undo a failed change and to recover after a crash. Two other types, a Lingoes source and a LaserDisc capture, share the ending.

How do I open an LDF file?

SQL Server opens it when the database comes online. To read the records from outside, use the fn_dblog function or a Windows viewer that reads the MDF and LDF files together. A text editor shows only symbols. We tested our own readers on Linux and used neither Windows tool.

Why does my LDF file cause an error?

Eight causes cover what we found. An LDF file can be full, missing or on the wrong path. The database can have shut down badly or be read only. The file can be cut or be another type, and a viewer can lack the MDF file. Error 9002 means the log is full.

Can I delete an LDF file?

Do not delete an LDF file of a database you use. Microsoft says attach can rebuild a missing log only for a read and write database that shut down cleanly, and a rebuild breaks the log backup chain. Keep every detached log file until the attach works. We tested no deletion.

Is an LDF file safe to share?

No, treat it like the database. In our LDF file, a deleted name and a rolled back change were still readable in the records. Microsoft also warns against attaching databases from unknown sources. Share an LDF file only with people you would trust with the data.

Why is my LDF file so big?

Two common reasons are that the LDF file is not being truncated or that a transaction is still open. Query log_reuse_wait_desc in sys.databases to see the reason. Microsoft lists values like LOG_BACKUP, ACTIVE_TRANSACTION and REPLICATION. Fix the reason before you shrink, because a shrink is not routine maintenance.

Can I shrink an LDF file?

Yes, with a shrink command, while the database is online and at least one VLF is free. Microsoft says a shrink returns free space to the operating system and should not be a regular task. AUTO_SHRINK is off by default, and Microsoft does not recommend turning it on.

What is the difference between LDF, MDF and BAK files?

An LDF file records the changes. An MDF file stores the data, and an NDF file adds more data space. A BAK file is a backup that SQL Server writes when you ask. A database has one MDF file and at least one LDF file.

Can I read an LDF file without SQL Server?

Yes, a little. Our 69 line script reads the headers, the blocks and the records of a healthy LDF file. Two Windows viewers read LDF files with the MDF file. Neither our script nor a viewer proves the records are the ones SQL Server wrote.

Can I see deleted rows in an LDF file?

In our LDF file, the name Ali Khan was readable in the insert record and in the delete record. We did not recover any row. The SysTools page says its trial shows 50 records per table and cannot export, so a full export needs the paid version.

Is an LDF file the same as a LaserDisc or Lingoes file?

No, but they share the ending. FileInfo lists a Lingoes dictionary source and a LaserDisc capture compressed with FLAC. The first bytes separate them. A SQL Server log starts with 01 0F, and a FLAC file starts with the letters fLaC. We tested neither of the other two on files from their own tools.

What is the MIME type of an LDF file?

We found none registered for the SQL Server type in the part of the IANA list we could read. The file command printed data for our LDF file. FLAC has the registered type audio/flac, which applies to the LaserDisc type only if its tool wrote ordinary FLAC.

Still Stuck With an LDF File? Two routes out, and where to look next

Your LDF file causes an error

Read the first bytes and follow the seven steps. The cause table lists what to try in order.

You want to share it safely

Read what an LDF file can contain, and then the checks before you share.

Is it the data file? An MDF file stores the tables. Our page on MDF files covers it, and the versus part shows how it relates to the LDF file.

Is it a similar ending? An LDIF file is a directory file, and an MDB file is an Access database. Our page on LDIF files and our page on MDB files cover them.

Is the data unknown? Our page on DAT files covers files with no clear type, and the file extension resource library lists many more.

Is your type missing? Send it on the submit an LDF file type page.