Troubleshooting Guide: SQL Server Error 3970
Why This Error Happens
Error 3970 occurs when multiple threads or processes attempt to issue conflicting commands (such as COMMIT, ROLLBACK, or BEGIN) against the same transaction simultaneously. This typically happens due to application code that reuses a connection or transaction object across multiple threads without proper synchronization, or when a previous command on the connection hasn’t fully completed (is still pending) before a new one is issued. In some cases, this is triggered by MARS (Multiple Active Result Sets) being improperly managed, or by an application timeout that fires a rollback while the original query is still executing.
Step-by-Step Resolution Guide
Step 1: Identify the Conflicting Session and Query
- Open SQL Server Management Studio (SSMS) and run
sp_who2or querysys.dm_exec_requeststo identify the session ID (SPID) throwing the error. - Check
sys.dm_tran_active_transactionsjoined withsys.dm_tran_session_transactionsto see if a single session has multiple open transactions. - Review the SQL Server error log at
C:\Program Files\Microsoft SQL Server\MSSQL17.MSSQLSERVER\MSSQL\Log\ERRORLOGfor the exact timestamp and context of the 3970 error.
Step 2: Audit Application Connection and Threading Logic
- Verify the application is not sharing a single
SqlConnectionorSqlTransactionobject across multiple threads concurrently. - Check the connection string for
MultipleActiveResultSets=True— if present, ensure the application correctly awaits each command before issuing another on the same connection. - Look for mismatched
BEGIN TRAN/COMMIT/ROLLBACKpairs in stored procedures, especially inside nested TRY/CATCH blocks where a ROLLBACK might fire while another batch is still active.
Step 3: Adjust Timeout and Retry Settings
- Increase the command timeout value in the application’s connection settings (default is often 30 seconds) to prevent premature ROLLBACK calls from the client while a long-running query is still active.
- Navigate to the application config (e.g.,
web.configorappsettings.json) and update theCommandTimeoutproperty. - Implement application-level retry logic using exponential backoff rather than immediate transaction aborts.
Step 4: Restart the Affected Session or Service
- If the issue persists on a specific SPID, kill the blocking session using
KILL <SPID>in SSMS. - If the conflict is widespread, restart the SQL Server service via
services.mscor runRestart-Service MSSQLSERVERin an elevated PowerShell prompt on Windows Server 2025. - Clear any orphaned connections by cycling the application’s connection pool (recycle the IIS App Pool or restart the service account).
Alternative or Verification Steps
- To verify the fix, run the application’s transaction-heavy workflow under load and monitor
sys.dm_tran_active_transactionsto confirm no session shows multiple simultaneous “ACTIVE” transaction states. - If the error persists after code review, as a workaround, disable MARS in the connection string and ensure each thread opens its own dedicated
SqlConnectioninstance.