Skip to content
Products
AI Website Builder New VPS Hosting Cloud Servers Web Hosting Dedicated Servers Domains
Company
About Documentation Support Center Contact Get Started Call +91 75795 45488
Login
Hosting Panel — cPanel & Billing Console Panel — VPS Management
ALL SYSTEMS OPERATIONAL
Troubleshooting

MySQL Deadlock Found: Causes and How to Fix It Fast

Getwebup 6 min read

Your site throws a WooCommerce order into an error state, or a WP-CLI import halts, and buried in the log is ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction. It looks alarming, but it's not corruption and it's not a crashed table — it's MySQL doing exactly what it's designed to do. Here's what's actually happening, why it tends to show up on busy WooCommerce and high-traffic WordPress sites, and how to stop it from recurring.

What a Deadlock Actually Is

InnoDB (the storage engine behind almost every modern WordPress and WooCommerce database) locks rows when a transaction updates them, so two processes can't corrupt the same data at once. A deadlock happens when two transactions each hold a lock the other one needs, and neither can proceed. MySQL detects this standoff and kills one of the transactions — the "victim" — to let the other one finish. That's the deadlock error you see.

This is normal, expected behaviour under concurrency, not a bug in MySQL. The problem is only that your application (WordPress, WooCommerce, a custom script) usually doesn't retry the failed transaction automatically, so the user sees a failed checkout, a stuck import, or a plugin that silently didn't save.

Where It Shows Up Most Often

  • WooCommerce checkout under load — multiple orders updating the same product's stock quantity in wp_postmeta at the same time.
  • WooCommerce sessions table (wp_woocommerce_sessions) — heavy traffic writing session data concurrently.
  • Bulk imports or updates — a WP-CLI or plugin script updating rows in a different order than a simultaneous cron job or another admin action.
  • Caching/cron plugins writing to wp_options or a transients table at the same moment a page load reads/writes the same autoloaded option.

Notice the pattern: it's almost always two processes touching the same rows, in a different order, at roughly the same time. Low-traffic sites rarely see this. Sites doing real concurrent writes — busy stores, membership sites, anything with WP-Cron piling up — see it regularly.

Confirm What's Actually Deadlocking

Don't guess. If you have SSH or cPanel Terminal access with MySQL privileges, pull the engine status right after (or during) an occurrence:

mysql -u root -p -e "SHOW ENGINE INNODB STATUS\G" | less

Scroll to the LATEST DETECTED DEADLOCK section. It lists both transactions, the exact queries involved, and which one was rolled back. This is the only reliable way to know which plugin, query, or cron job is actually colliding — guessing from the error message alone wastes time.

On shared cPanel hosting without root MySQL access, check WordPress → Site Health → Info → Database for slow queries, or enable WordPress debug logging (WP_DEBUG_LOG) and watch wp-content/debug.log around the time the error occurs — the failing query usually gets logged by whichever plugin issued it.

Fixing It

1. Make WordPress/WooCommerce retry automatically

Most single-occurrence deadlocks are harmless if the transaction just retries — that's literally what the error message tells MySQL's client to do. WooCommerce already retries some internal queries, but a custom plugin or script usually doesn't. If you're the one writing the query (a custom plugin, a migration script), wrap it:

global $wpdb;
$attempts = 0;
do {
    $result = $wpdb->query( $sql );
    $deadlocked = ( $wpdb->last_error && strpos( $wpdb->last_error, 'Deadlock' ) !== false );
    $attempts++;
} while ( $deadlocked && $attempts < 3 );

That alone silently fixes the vast majority of deadlock-related order failures.

2. Reduce lock contention at the source

If the same deadlock keeps recurring between the same two operations, retrying just delays the inevitable. Fix the actual contention:

  • WooCommerce stock sync — enable WooCommerce → Settings → Products → Inventory → Hold stock reasonably (don't set it to 0) and consider disabling "manage stock" on products that don't need real-time inventory, which removes a lot of the row-locking on wp_postmeta.
  • Move to HPOS (High-Performance Order Storage) if you haven't — it stores orders in dedicated tables instead of overloading wp_posts/wp_postmeta, which was never designed for that write volume.
  • Stagger cron jobs — if WP-Cron and a system cron job (or two plugins) both fire near the same minute and touch the same options, spread them out. Check cPanel → Cron Jobs and any plugin-scheduled events with wp cron event list.
  • Add missing indexes — deadlocks get more likely when a query without a proper index locks far more rows (or a full table scan) than it needs to. Check slow queries with EXPLAIN on the query from the deadlock output; a missing index on a WHERE or JOIN column is a common root cause.

3. Tune InnoDB lock settings (VPS/root access only)

On a VPS where you manage my.cnf yourself, two settings matter:

SettingWhat it doesReasonable value
innodb_lock_wait_timeoutHow long a transaction waits for a lock before giving up (this is a separate error from deadlock, but related)50 (default is usually fine)
innodb_deadlock_detectWhether InnoDB actively looks for deadlocks vs waiting out the timeoutON (default, keep it on)
innodb_print_all_deadlocksLogs every deadlock to the error log, not just the latest oneON while diagnosing a recurring issue

Turn on innodb_print_all_deadlocks temporarily if deadlocks are frequent enough that SHOW ENGINE INNODB STATUS keeps missing them between checks:

mysql -u root -p -e "SET GLOBAL innodb_print_all_deadlocks = ON;"

Every deadlock then lands in the MySQL error log (usually /var/log/mysqld.log or /var/lib/mysql/hostname.err on a VPS), which gives you a running history instead of a single snapshot.

4. Keep transactions short

The longer a transaction holds its locks, the bigger the window for another process to collide with it. If a custom script wraps a large batch of updates in one transaction, break it into smaller batches with commits in between — a bulk price update on 50,000 products as one transaction is a deadlock waiting to happen; the same update in batches of 500 almost never is.

Prevention Going Forward

  • Keep WooCommerce, WordPress core, and any plugin touching orders or stock fully updated — lock-contention bugs get patched regularly.
  • Move to HPOS if you're still on legacy post-based order storage and run a serious store.
  • Avoid stacking heavy cron jobs (backups, imports, report generation) at the same time as peak traffic.
  • If you're on shared cPanel hosting and deadlocks correlate with traffic spikes, that's often a sign the account has outgrown shared resources — a VPS with dedicated MySQL resources removes a lot of this contention entirely.
  • Monitor SHOW ENGINE INNODB STATUS or your error log after any big plugin update, since a new plugin querying the same tables differently is a common trigger for a fresh round of deadlocks.

One or two deadlocks a week on a busy store is normal and self-healing as long as retries are in place. Dozens a day, or the same query pair showing up every time, means it's time to fix the actual contention rather than keep retrying around it.

Frequently asked questions

Is a MySQL deadlock the same as a crashed table?

No. A crashed table means data corruption and needs a repair (CHECK TABLE / REPAIR TABLE). A deadlock is MySQL correctly resolving a lock conflict between two transactions by rolling one back — no data is damaged, and the table doesn't need repairing.

Will a deadlock cause me to lose the WooCommerce order?

Only if nothing retries the failed transaction. WooCommerce retries some of its own internal writes, but a custom plugin or script that doesn't check for the deadlock error and retry can leave an order half-written. Adding a simple retry loop around custom queries fixes this.

Can I just increase innodb_lock_wait_timeout to stop this?

That setting controls how long a transaction waits before timing out — it's a different error (lock wait timeout exceeded) from a deadlock, which InnoDB detects and resolves immediately. Raising it won't stop deadlocks; it can actually make lock contention worse by letting transactions hold locks longer.

Why do deadlocks only happen on my store during sales or traffic spikes?

Deadlocks need concurrency — two transactions touching the same rows at the same time. Low traffic rarely creates that overlap. During a sale, many customers checking out at once all update the same product stock rows within milliseconds of each other, which is exactly the pattern that triggers it.

Does switching to HPOS actually reduce deadlocks?

Usually, yes. Legacy order storage crams orders into wp_posts and wp_postmeta alongside every other post type, meta key, and plugin query on the same tables. HPOS gives orders their own dedicated tables, which removes a lot of the incidental lock contention that has nothing to do with orders at all.

#mysql #deadlock #innodb #woocommerce #wordpress #database-locking

Keep reading

Chat with Support