MySQL
database management
foreign key constraint
index
SQL error

MySQL Cannot drop index needed in a foreign key constraint

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

MySQL error 1553 ("Cannot drop index 'index_name': needed in a foreign key constraint") means you are trying to remove an index that MySQL is currently using to enforce a foreign key relationship. MySQL requires an index on the foreign key columns of both the parent and child tables. If you try to drop that index while the foreign key constraint still references it, MySQL blocks the operation to protect referential integrity. The fix is to drop the foreign key constraint first, then drop the index, and optionally recreate the constraint afterward.

Why MySQL Requires Indexes for Foreign Keys

Unlike PostgreSQL, which can enforce foreign keys without a dedicated index (though it recommends one for performance), MySQL's InnoDB engine requires an index on the referencing columns. When you create a foreign key, InnoDB automatically creates an index on the child table's foreign key columns if one does not already exist. This index is used to efficiently check constraint violations during inserts, updates, and deletes.

The parent table's referenced columns must also be indexed. Typically this is the primary key, but it can be any unique index.

sql
1CREATE TABLE customers (
2    customer_id INT PRIMARY KEY,
3    name VARCHAR(100) NOT NULL,
4    email VARCHAR(255)
5);
6
7CREATE TABLE orders (
8    order_id INT PRIMARY KEY,
9    order_date DATE NOT NULL,
10    customer_id INT,
11    INDEX idx_orders_customer_id (customer_id),
12    CONSTRAINT fk_orders_customer
13        FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
14);

In this example, idx_orders_customer_id is the index that supports the foreign key fk_orders_customer. Dropping this index triggers error 1553.

Reproducing the Error

sql
-- This fails with ERROR 1553
ALTER TABLE orders DROP INDEX idx_orders_customer_id;
text
ERROR 1553 (HY000): Cannot drop index 'idx_orders_customer_id': needed in a foreign key constraint

MySQL is telling you that removing the index would leave the foreign key constraint without the index it needs to function.

Step-by-Step Fix

Step 1: Identify the Foreign Key Constraint

Before dropping anything, find out which foreign keys depend on the index. Use INFORMATION_SCHEMA to query the relationships:

sql
1SELECT
2    CONSTRAINT_NAME,
3    TABLE_NAME,
4    COLUMN_NAME,
5    REFERENCED_TABLE_NAME,
6    REFERENCED_COLUMN_NAME
7FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
8WHERE TABLE_SCHEMA = 'your_database'
9  AND TABLE_NAME = 'orders'
10  AND REFERENCED_TABLE_NAME IS NOT NULL;

This returns the constraint name (e.g., fk_orders_customer), which you need for the next step.

You can also use SHOW CREATE TABLE for a quick view:

sql
SHOW CREATE TABLE orders;

The output includes all constraints and indexes, making it easy to see which index belongs to which foreign key.

Step 2: Drop the Foreign Key Constraint

sql
ALTER TABLE orders DROP FOREIGN KEY fk_orders_customer;

This removes the constraint but leaves the index in place. MySQL does not automatically drop the index when you drop the foreign key.

Step 3: Drop the Index

Now the index is no longer required by any constraint:

sql
ALTER TABLE orders DROP INDEX idx_orders_customer_id;

Step 4: Recreate the Foreign Key (If Needed)

If you still need the referential integrity but wanted to replace the index (e.g., changing it to a composite index), recreate the constraint:

sql
1-- Create a new composite index
2ALTER TABLE orders ADD INDEX idx_orders_customer_date (customer_id, order_date);
3
4-- Recreate the foreign key using the new index
5ALTER TABLE orders ADD CONSTRAINT fk_orders_customer
6    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
7    ON DELETE CASCADE
8    ON UPDATE CASCADE;

MySQL will use the new composite index to enforce the foreign key, as long as the foreign key columns are a leftmost prefix of the index.

Doing It in a Single ALTER TABLE

MySQL allows combining multiple operations in one ALTER TABLE statement, which is faster because it only rebuilds the table once:

sql
1ALTER TABLE orders
2    DROP FOREIGN KEY fk_orders_customer,
3    DROP INDEX idx_orders_customer_id,
4    ADD INDEX idx_orders_customer_date (customer_id, order_date),
5    ADD CONSTRAINT fk_orders_customer
6        FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
7        ON DELETE CASCADE;

This approach reduces downtime on large tables because InnoDB performs a single table rebuild instead of four separate ones.

Using FOREIGN_KEY_CHECKS as a Last Resort

In maintenance windows or migrations, you can temporarily disable foreign key checks:

sql
1SET FOREIGN_KEY_CHECKS = 0;
2
3ALTER TABLE orders DROP INDEX idx_orders_customer_id;
4
5SET FOREIGN_KEY_CHECKS = 1;

This bypasses the protection and lets you drop the index without first removing the constraint. However, this is risky. If you forget to recreate the supporting index, queries that rely on the foreign key relationship will perform full table scans, and data integrity checks will be less efficient.

Only use this approach during controlled migrations, never in application code.

Finding All Foreign Key Dependencies in a Database

When you are refactoring indexes across multiple tables, it helps to see all foreign key relationships at once:

sql
1SELECT
2    kcu.TABLE_NAME AS child_table,
3    kcu.COLUMN_NAME AS child_column,
4    kcu.CONSTRAINT_NAME AS fk_name,
5    kcu.REFERENCED_TABLE_NAME AS parent_table,
6    kcu.REFERENCED_COLUMN_NAME AS parent_column,
7    rc.UPDATE_RULE,
8    rc.DELETE_RULE
9FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
10JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
11    ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
12    AND kcu.TABLE_SCHEMA = rc.CONSTRAINT_SCHEMA
13WHERE kcu.TABLE_SCHEMA = 'your_database'
14  AND kcu.REFERENCED_TABLE_NAME IS NOT NULL
15ORDER BY kcu.TABLE_NAME, kcu.CONSTRAINT_NAME;

This gives you a complete map of foreign keys, their supporting columns, and the cascade rules, which is essential before making index changes.

Index Selection Rules for Foreign Keys

MySQL selects an index for a foreign key based on specific rules. Understanding these prevents surprises:

RuleExampleSupported?
Exact match on FK columnsINDEX (customer_id) for FK on customer_idYes
Leftmost prefix of composite indexINDEX (customer_id, order_date) for FK on customer_idYes
Non-leftmost column of composite indexINDEX (order_date, customer_id) for FK on customer_idNo
Unique indexUNIQUE (customer_id) for FK on customer_idYes
Primary keyPRIMARY KEY (customer_id) for FK on customer_idYes

The key takeaway: a composite index only satisfies a foreign key if the FK columns are a leftmost prefix of the index columns. INDEX (a, b) works for a foreign key on (a) but not for a foreign key on (b).

Common Pitfalls

Trying to drop the index before the foreign key. MySQL enforces the dependency strictly. Always drop the foreign key first, then the index. Or combine both in a single ALTER TABLE statement.

Assuming MySQL auto-drops the index when you drop the foreign key. It does not. After dropping a foreign key, the auto-created index remains and must be removed separately if you no longer need it.

Using FOREIGN_KEY_CHECKS = 0 without re-enabling it. If your session ends abnormally or you forget to reset it, subsequent sessions are not affected (it is session-scoped), but data inserted during that session will not be validated.

Not checking which index the foreign key uses. If you have multiple indexes that could satisfy the foreign key (e.g., both INDEX (customer_id) and INDEX (customer_id, status)), MySQL uses one of them. Dropping the "wrong" one might succeed while dropping the one MySQL chose triggers the error. Use SHOW CREATE TABLE to see which index is associated with the constraint.

Forgetting cascade rules when recreating. When you drop and recreate a foreign key, remember to specify ON DELETE and ON UPDATE rules. The default is RESTRICT, which may differ from what the original constraint had.

Summary

  • Error 1553 means the index is required by a foreign key constraint and cannot be dropped independently.
  • Drop the foreign key first with ALTER TABLE ... DROP FOREIGN KEY, then drop the index.
  • Combine both operations in a single ALTER TABLE statement to minimize table rebuilds on large tables.
  • Use INFORMATION_SCHEMA.KEY_COLUMN_USAGE or SHOW CREATE TABLE to identify which constraints depend on which indexes.
  • A composite index satisfies a foreign key only if the FK columns are a leftmost prefix of the index.
  • SET FOREIGN_KEY_CHECKS = 0 is a last resort for controlled migrations, not regular application use.
  • MySQL does not auto-drop indexes when you drop foreign keys. Clean up orphaned indexes manually.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.