Databases 7 min read

Why Insert‑Into‑Select Can Crash Your MySQL and How to Prevent It

A real‑world MySQL incident shows that using INSERT INTO SELECT without proper indexing can trigger full table scans, lock tables, cause OOM and data loss, while a careful analysis and adding indexes can safely resolve the issue.

macrozheng
macrozheng
macrozheng
Why Insert‑Into‑Select Can Crash Your MySQL and How to Prevent It

Background

The company processes millions of rows daily in a single MySQL table and needed to migrate old data without sharding.

Proposed solutions

Load data via a program, insert into a history table, then delete the original rows.

Use INSERT INTO SELECT to let the database handle the migration.

The first method caused an OOM error when loading all data at once, so the team chose the second method.

What went wrong

Typical pseudo‑code for the first approach demonstrates loading the entire result set into memory:

// 1. Query data to migrate
List<Object> list = selectData();

// 2. Insert into history table
insertData(list);

// 3. Delete original rows
deleteByIds(ids);

During the nightly migration the team used INSERT INTO SELECT with a date filter (retain only the last 10 days). The SELECT part performed a full table scan, locking the target table and causing intermittent insert failures, which resulted in missing payment records.

The execution plan clearly shows a full table scan.

Root cause analysis

In the default transaction isolation level, INSERT INTO a SELECT b locks table a while scanning b row‑by‑row; the full scan caused extensive locking and timeouts.

Testing missed the issue because the test environment used realistic data volume but did not simulate the large‑scale nightly insert, so the problem only appeared in production.

Solution

Avoid full table scans by adding appropriate indexes on the columns used in the WHERE clause of the SELECT statement, ensuring the query uses the index and does not lock the whole table.

Conclusion

Use INSERT INTO SELECT with caution; always verify that the SELECT part is indexed and consider its impact on transaction isolation to prevent OOM and data loss.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

INSERT INTO SELECTFull Table Scan
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.