Common SQL Errors

MySQL Error 3058: ER_USER_LOCK_DEADLOCK - How to Fix and Prevent

Galaxy Team
August 8, 2025

MySQL returns ER_USER_LOCK_DEADLOCK (error 3058, SQLSTATE HY000) when GET_LOCK or RELEASE_LOCK enters a mutual wait, causing a user-level lock deadlock.

Sign up for the latest in common SQL errors from the Galaxy Team!
Welcome to the Galaxy, Guardian!
You'll be receiving a confirmation email

Follow us on twitter :)
Oops! Something went wrong while submitting the form.

What is MySQL error 3058 ER_USER_LOCK_DEADLOCK?

ER_USER_LOCK_DEADLOCK appears when two sessions wait on each other’s named locks. Release or time-out conflicting locks, commit or roll back open transactions, and retry GET_LOCK to resolve the deadlock.

Error Highlights

Typical Error Message

ER_USER_LOCK_DEADLOCK

Error Type

Locking Error

Language

MySQL

Symbol

rolling back transaction/releasing locks and restarting lock acquisition. This error is returned when the metdata locking subsystem detects a deadlock for an attempt to acquire a named lock with GET_LOCK. ER_USER_LOCK_DEADLOCK was added in 5.7.5.

Error Code

3058

SQL State

HY000

Explanation

Table of Contents

What is ER_USER_LOCK_DEADLOCK?

The message Deadlock found when trying to get user-level lock means MySQL detected a cyclic wait between sessions using GET_LOCK or RELEASE_LOCK. Each session is holding a named lock that the other needs, so progress halts until the server intervenes.

Since version 5.7.5 MySQL aborts one participant, rolls back its statement, and returns error 3058 with SQLSTATE HY000. The connection remains open, but the failed lock was not acquired.

What Causes This Error?

Most cases arise when application threads rely on the same lock names for different tasks without a strict ordering policy. Concurrent GET_LOCK calls with overlapping names can quickly form a cycle.

Long transactions that keep metadata locks open compound the problem, because GET_LOCK waits while table-level locks from the other session remain active.

How to Fix ER_USER_LOCK_DEADLOCK

Choose one blocked session as the survivor, explicitly RELEASE_LOCK in the other, and retry. If retry logic already exists, simply catch error 3058 and run GET_LOCK again after a short sleep.

Reduce risk by keeping named-lock scope narrow: acquire just before the critical section and release immediately afterward or by COMMIT.

Common Scenarios and Solutions

Background workers inserting into the same queue table often use GET_LOCK('queue_write'). Stagger their schedules or use lock names derived from primary keys to avoid contention.

Online schema changes that rely on metadata locks can collide with application-level GET_LOCK calls. Run DDL in maintenance windows or separate connections that never request user locks.

Best Practices to Avoid This Error

Adopt a global naming convention that encodes resource hierarchy, eg project:task:id, so sessions acquire locks in identical order.

Set a low timeout on GET_LOCK calls, e.g., 2 seconds, to let applications fail fast and retry rather than hang indefinitely.

Related Errors and Solutions

ER_LOCK_DEADLOCK (1213) is similar but occurs with row or metadata locks, not user-level locks. Handle it by rolling back and retrying the entire transaction.

Common Causes

Overlapping GET_LOCK Names

Different code paths request the same lock names simultaneously without coordination.

Long Transactions Holding Locks

Sessions keep metadata or table locks open, blocking subsequent GET_LOCK attempts.

Missing Lock Acquisition Order

Applications acquire multiple named locks in varying sequences, creating circular wait chains.

High GET_LOCK Timeout Values

Indefinite waits allow cycles to persist long enough for the server to detect a deadlock.

Related Errors

ER_LOCK_DEADLOCK (1213)

Deadlock detected among transactional row locks; resolved by rolling back one transaction.

ER_LOCK_WAIT_TIMEOUT (1205)

Row or metadata lock wait exceeded innodb_lock_wait_timeout.

ER_METADATA_LOCK_EXPIRED (4050)

Metadata lock failed to be released before timeout during online DDL.

FAQs

Does ER_USER_LOCK_DEADLOCK roll back my transaction?

Only the statement requesting GET_LOCK is aborted. Open transactions remain active unless you explicitly roll back.

Can I disable user-level locks?

No. You can avoid them by refactoring code but MySQL provides no server flag to disable GET_LOCK.

What timeout should I use for GET_LOCK?

Set a small value, such as 2 seconds, to minimize impact and allow quick retries.

How does Galaxy help?

Galaxy’s query history highlights aborted statements, helping you spot frequent ER_USER_LOCK_DEADLOCK errors and refactor lock usage patterns.

Start Querying with the Modern SQL Editor Today!
Welcome to the Galaxy, Guardian!
You'll be receiving a confirmation email

Follow us on twitter :)
Oops! Something went wrong while submitting the form.

Check out some other errors

Trusted by top engineers on high-velocity teams
Aryeo Logo
Assort Health
Curri
Rubie Logo
Bauhealth Logo
Truvideo Logo