Skip to content

Est. 2011ยทMicrosoft Partner 7033487ยทDelivery under 3 minยทSupport 7 days a week

Your vault is empty.

License Error 3967

Error 3967: Insufficient Space in tempdb to Hold Row Versions

12 min read Updated October 5, 2026 SQL Server

Fix it now

tempdb filled with row versions and your transaction was chosen as the one to sacrifice. The version store holds previous images of rows so that readers under row versioning see a consistent picture without blocking writers, and cleanup cannot pass the oldest transaction that might still need them. One forgotten transaction fills a large tempdb with everybody else’s versions.

Run both in the tempdb context: the first says what is filling it, the second says who

USE tempdb;
SELECT SUM(version_store_reserved_page_count)   * 8 / 1024 AS version_mb,
       SUM(user_object_reserved_page_count)     * 8 / 1024 AS user_mb,
       SUM(internal_object_reserved_page_count) * 8 / 1024 AS internal_mb
FROM   sys.dm_db_file_space_usage;

SELECT session_id, transaction_id, transaction_sequence_num, elapsed_time_seconds
FROM   sys.dm_tran_active_snapshot_database_transactions
ORDER BY elapsed_time_seconds DESC;
  1. If the version figure dominates, this is your problem. If internal objects dominate instead, you are looking at sorts and hashes spilling out of memory, which is a query tuning problem and a different article.
  2. Take the top session from the second query and see what it is doing: SELECT session_id, status, command, last_request_start_time FROM sys.dm_exec_requests WHERE session_id = <spid>;
  3. End it if it is abandoned, or let it finish if it is genuine work. Cleanup resumes once the oldest transaction is gone.
  4. Confirm which versioning options are on: SELECT name, snapshot_isolation_state_desc, is_read_committed_snapshot_on FROM sys.databases;
  5. Give tempdb room: pre-size its files on a volume of their own, with fixed growth increments rather than percentages.

internal_object_reserved_page_count is only meaningful in tempdb, because internal objects exist nowhere else. Run the first query in the tempdb context or the numbers will not mean what you think.

If the version store is falling and the workload is running, you are done. If it fills again tomorrow, the next section explains why cleanup stalls.

Why it happens

When row versioning is in use, updating or deleting a row copies its previous image into the version store in tempdb and leaves a pointer behind. A reader that started earlier follows the chain back to the version it is entitled to see. That is what allows readers not to block writers, and it is the mechanism behind both read committed snapshot isolation and explicit snapshot isolation. Microsoft also lists the other features that generate versions in the same store: online index operations, multiple active result sets, and AFTER triggers.

A background task removes versions that no transaction can still need, and it works out that boundary from the oldest active transaction. A single long-running one therefore holds the whole store open. The store then grows at the rate of your write workload, not at the rate of anything the long transaction is doing, which is why an idle session with an open transaction can fill tempdb overnight while appearing to do nothing at all.

The related codes are not all about capacity, and that is worth being precise about. 3959 is the version store reporting itself full and warning that a transaction needing it may be rolled back. 3958 is a reader that went looking for a versioned row and did not find it. 3966 is a transaction being rolled back because it was marked as a victim earlier, when the version store was shrunk. 3964 is different in kind: it means a DDL statement was issued inside a snapshot isolation transaction, which is not allowed. It has nothing to do with tempdb capacity and it will not be fixed by adding space.

One long transaction is preventing cleanup

You have this one if The snapshot transactions view shows a session open for hours, and the version store keeps growing while it exists.

  1. Identify the owner: SELECT session_id, login_name, host_name, program_name FROM sys.dm_exec_sessions WHERE session_id = <spid>;
  2. Decide with them whether it can be ended. KILL rolls it back, and a large rollback takes time and resources.
  3. Look for the pattern behind it: a transaction left open across user input, one opened before a slow external call, or a forgotten BEGIN TRANSACTION in a query window.
  4. Confirm the version store starts shrinking once the transaction is gone.

tempdb is too small or cannot grow

You have this one if The version store is large but not unreasonable, and tempdb’s files are at their maximum or the volume is full.

  1. Pre-size the tempdb data files rather than relying on growth, and give every data file the same initial size and growth settings.
  2. Set fixed growth increments in megabytes and remove percentage growth.
  3. Put tempdb on its own volume where you can, so a busy hour does not fill the volume holding user databases.
  4. Restart the instance after changing file sizes. tempdb is recreated at startup from the settings you configure.

Microsoft’s stated reason for identical file sizes is the proportional-fill algorithm: allocations favour the file with the most free space, so unequal files produce unequal load.

Read committed snapshot isolation was enabled without sizing for it

You have this one if The problem appeared after someone turned on RCSI to reduce blocking, and tempdb has not changed since.

  1. Confirm it is on with the sys.databases query above.
  2. Size tempdb for the write volume of the busiest database, not for its idle state.
  3. Monitor the version store size and the version generation and cleanup rates through the Transactions performance counters over a full business cycle.
  4. If the workload turns out not to need it, turn it off deliberately: ALTER DATABASE [MyDb] SET READ_COMMITTED_SNAPSHOT OFF WITH ROLLBACK IMMEDIATE; disconnects users at that moment.

Long reporting queries against the transactional database

You have this one if Version pressure peaks when reports run, and the sessions holding the oldest transactions are read-only.

  1. Move the reporting workload off the transactional instance where you can, to a restored copy or a readable secondary.
  2. Break long report transactions into shorter ones so the cleanup boundary keeps advancing.
  3. Check for reports holding one transaction open across the whole run without needing to.

Accelerated Database Recovery, available from SQL Server 2019 and off by default, keeps a persistent version store on the PRIMARY filegroup of the user database rather than in tempdb. Enabling it changes this picture for that database.

3964, which is not a space problem at all

You have this one if The message says a DDL statement is not allowed inside a snapshot isolation transaction, and no tempdb figure is unusual.

  1. Move the DDL out of the snapshot isolation transaction. This is a code change, not a configuration change.
  2. Check whether the session set SNAPSHOT isolation explicitly, or whether it inherited it.
  3. Do not add tempdb space in response to this one. It will not help.

Full reference

What is actually filling tempdb

What dominates tempdb What it means
Version store pages Row versioning. This article’s problem; find the oldest transaction
Internal object pages Sorts, hashes and spools spilling out of memory. A query tuning problem
User object pages Temporary tables and table variables created by application code
Nothing dominates but tempdb is small A sizing problem. tempdb was never given room for this workload
A session with a huge elapsed_time_seconds in the snapshot transactions view That is your blocker

The five codes, and which are about space

Code Published meaning About space?
3967 Insufficient space in tempdb to hold row versions. Need to shrink the version store to free up some space Yes
3958 Transaction aborted when accessing a versioned row. The requested versioned row was not found Indirectly: the version was already cleaned up
3966 Transaction is rolled back when accessing the version store. It was earlier marked as victim when the version store was shrunk Yes, as an after-effect
3959 Version store is full. New versions could not be added. A transaction that needs to access the version store may be rolled back Yes
3964 Transaction failed because this DDL statement is not allowed inside a snapshot isolation transaction No. This is a code problem

What generates versions besides your isolation level

  • Data modifications in a database using read committed snapshot isolation or snapshot isolation.
  • Online index operations, which version rows while the index is being built.
  • Multiple active result sets, which needs versions to keep interleaved result sets consistent.
  • AFTER triggers, which read the previous image of the modified rows.
  • So a database with no snapshot isolation at all can still put pressure on the version store, and the first three of those are easy to overlook when the isolation level looks innocent.

Accelerated Database Recovery, and where its versions live

Accelerated Database Recovery is available from SQL Server 2019 and is off by default. When it is enabled on a user database, its persistent version store lives on the PRIMARY filegroup of that database rather than in tempdb, which takes that database’s versioning pressure off tempdb entirely and puts it on the user database’s own files instead. That is a trade rather than a saving, and it needs to be planned for in the data file sizing.

In SQL Server 2025 there is a further wrinkle worth knowing before you size anything. When Accelerated Database Recovery is enabled in tempdb itself, tempdb holds two independent version stores: the traditional one, used for versions generated by user databases that do not have ADR enabled, and a persistent version store used for versions generated by transactions in tempdb. Microsoft’s guidance is to allocate enough space in the tempdb data files for both.

Sizing tempdb from measurement

  1. Watch the version store size across a full business cycle, not a quiet afternoon, using the Transactions performance counters and the file space usage query above.
  2. Take the maximum you observe and adjust it for the concurrency you expect, then set the file sizes to that.
  3. Give every data file the same initial size and growth settings, because the proportional-fill algorithm favours the file with the most free space.
  4. Use fixed increments in megabytes, never percentages.
  5. Remember that tempdb is recreated from those settings at every start, so configure the size you want rather than growing into it each day.
  6. If ADR is enabled in tempdb on SQL Server 2025, size for both version stores.

When a licence is the actual fix

Almost every 3967 is solved by ending a long transaction and sizing tempdb properly, and neither costs anything. Where an edition genuinely becomes the ceiling is at the bottom of the range: in SQL Server 2025 Express caps the maximum relational database size at 50 GB, limits compute to the lesser of one socket or four cores, and caps the buffer pool at 1,410 MB. A version-heavy workload on those numbers spends its life short of memory, which pushes more work through tempdb rather than less. If that is where you are running, Arco supplies SQL Server 2025 Standard in two-core packs and can work out how many packs your server needs. Deal with the transaction and the tempdb files first; only look at the licence if the edition itself is what is stopping you.

Every code this article covers

Code What it points at Source
3967 Insufficient space in tempdb to hold row versions. The version store needs to be shrunk to free space in tempdb Microsoft Learn
3958 Transaction aborted when accessing a versioned row in a named table and database. The requested versioned row was not found Microsoft Learn
3966 Transaction is rolled back when accessing the version store. It was earlier marked as a victim when the version store was shrunk Microsoft Learn
3959 Version store is full. New versions could not be added. A transaction that needs to access the version store may be rolled back Microsoft Learn
3964 Transaction failed because this DDL statement is not allowed inside a snapshot isolation transaction. Not a capacity problem Microsoft Learn

Confirm the fix worked

  1. Re-run the tempdb usage query and confirm the version store figure is falling.
  2. Confirm no session in sys.dm_tran_active_snapshot_database_transactions has an unreasonable elapsed_time_seconds.
  3. Check the error log for further 3967 or 3959 entries after the change.
  4. Confirm tempdb’s files are at the sizes you configured after the next instance restart, and that they are all equal.
  5. Watch the version store across a full business cycle before concluding it is sized correctly.

Questions people ask about this

Will a licence or a bigger edition fix this?

Not directly. No edition makes tempdb bigger or cleans the version store sooner, and the fix is nearly always operational. Edition only matters if you are on Express, whose SQL Server 2025 limits – 50 GB per database, the lesser of one socket or four cores, and 1,410 MB of buffer pool – are the real constraint.

I got 3964 and adding tempdb space did nothing. Why?

Because 3964 is not a capacity error. Its published meaning is that a DDL statement is not allowed inside a snapshot isolation transaction. It is a code change, not a configuration change, and it happens to share a number range with the version store errors.

How big should tempdb be for row versioning?

Big enough for the versions generated between the start and end of your longest legitimate transaction, plus normal sort and temporary table use. Measure it from the version store counters across a full week rather than guessing, and leave headroom. On SQL Server 2025 with Accelerated Database Recovery enabled in tempdb, size for two version stores.

Is it safe to kill the long transaction?

It is safe in that the database stays consistent, because the transaction rolls back. It is not free: the rollback can take as long as the work it is undoing, and it holds resources while it runs.

Does turning off snapshot isolation solve it?

It removes that source of versions, but it brings back the blocking that made someone enable it, and it does not stop online index operations, multiple active result sets or AFTER triggers generating versions. Treat it as a workload decision, not a fix, and make it deliberately with the application team.

Related error codes

Was this article helpful?

Your feedback helps us improve our documentation.

Related articles

Free Fix Error 7202: Linked Server Missing From sys.servers and Ad Hoc Query Blocks Free Fix Errors 18487 and 18488: Expired SQL Logins and Password Policy Blocks Free Fix Error 17113: SQL Server Cannot Find or Open master.mdf at Startup License Error Error 701: Insufficient System Memory on a Memory-Capped SQL Server Edition
โ† Back to Knowledge Base