How to Fix MySQL Error 1036: Table Is Read Only

ERROR 1036 (HY000): Table '<table_name>' is read only is raised when MySQL receives a write operation (INSERT, UPDATE, DELETE, REPLACE, TRUNCATE, or DDL) against a table that cannot be modified. The error symbol is ER_OPEN_AS_READONLY.

Impact

Any statement that attempts to modify data or structure in the affected table is immediately rejected with this error. The statement does not execute, and if it is part of a larger transaction, the transaction is left in an open state — the application must roll it back or commit the preceding work before proceeding. No data is changed.

Developers typically encounter this in three situations: running write queries against a read replica, using a table that was placed in a read-only InnoDB tablespace, or when the underlying .ibd / .MYD / .MYI files on disk lack write permissions for the MySQL process user. ORMs surface this as a generic database exception — for example, Django raises django.db.utils.OperationalError, SQLAlchemy raises sqlalchemy.exc.OperationalError, and Hibernate raises javax.persistence.PersistenceException — each wrapping the original MySQL error message.

Common Causes

  1. Query sent to a read replica. In a primary/replica setup the replica runs with read_only=ON or super_read_only=ON. Any write from an application connection (not the replication thread) is rejected with 1036. This is the most common production cause.

  2. Global or session read_only variable is set. The server or session has read_only=ON. Users without the SUPER privilege (or CONNECTION_ADMIN in MySQL 8.0+) cannot write even to tables they own.

  3. super_read_only=ON is active. Even SUPER users are blocked. This mode is used on replicas managed by Group Replication or MySQL InnoDB Cluster to prevent accidental writes.

  4. InnoDB tablespace opened in read-only mode. The server was started with --innodb-read-only=1, placing every InnoDB table in a globally read-only state. This is sometimes used for point-in-time analysis of a backup.

  5. File system permissions. The .ibd file (InnoDB) or .MYD/.MYI files (MyISAM) are owned by a different user or are set to read-only on disk, so the mysql OS process cannot write to them.

  6. MyISAM table marked crashed or locked. A corrupted or improperly closed MyISAM table may be opened in read-only mode by the storage engine until it is repaired.

Troubleshooting and Resolution Steps

  1. Check read-only variables on the current server:

    SHOW VARIABLES LIKE 'read_only';
    SHOW VARIABLES LIKE 'super_read_only';
    SHOW VARIABLES LIKE 'innodb_read_only';
    

    If read_only is ON and you are on a replica, this is expected behavior — route write traffic to the primary. If you are on the primary and read_only is unexpectedly ON, disable it (requires SUPER or SYSTEM_VARIABLES_ADMIN):

    SET GLOBAL read_only = OFF;
    -- Also clear super_read_only if set:
    SET GLOBAL super_read_only = OFF;
    
  2. Identify whether the current server is a replica:

    -- MySQL 8.0.22+
    SHOW REPLICA STATUS\G
    
    -- MySQL 5.7 / 8.0 before 8.0.22
    SHOW SLAVE STATUS\G
    

    If Replica_IO_Running (or Slave_IO_Running) is Yes, the server is a replica. Configure your application's connection string or database driver to route writes to the primary host.

  3. Check whether innodb_read_only is active:

    SHOW VARIABLES LIKE 'innodb_read_only';
    

    If ON, the server was started with --innodb-read-only. Restart MySQL without that flag to allow writes.

  4. Inspect file system permissions for the affected table (run as root or the OS user that owns the MySQL data directory):

    ls -la /var/lib/mysql/<database_name>/<table_name>.ibd
    # For MyISAM:
    ls -la /var/lib/mysql/<database_name>/<table_name>.MYD
    ls -la /var/lib/mysql/<database_name>/<table_name>.MYI
    

    Restore ownership and permissions so the mysql user can write:

    chown mysql:mysql /var/lib/mysql/<database_name>/<table_name>.ibd
    chmod 660 /var/lib/mysql/<database_name>/<table_name>.ibd
    
  5. Repair a crashed MyISAM table that was opened read-only by the engine:

    REPAIR TABLE <table_name>;
    -- Or from the shell:
    -- myisamchk --recover /var/lib/mysql/<database_name>/<table_name>
    
  6. Verify the user's privileges are not somehow restricted (though 1036 is a server-level or file-level restriction, not a privilege issue — that would be error 1142):

    SHOW GRANTS FOR CURRENT_USER();
    

Additional Information

  • Related error codes: Error 1142 (ER_TABLEACCESS_DENIED_ERROR) is raised when a user lacks the INSERT/UPDATE/DELETE privilege — distinct from 1036, which is a server-state or file-system issue. Error 1290 (ER_OPTION_PREVENTS_STATEMENT) is raised when --read-only is passed as a command-line option and a write is attempted by a non-SUPER user.
  • MySQL 8.0 privilege change: In MySQL 8.0, the SUPER privilege was split into fine-grained dynamic privileges. To disable read_only on 8.0+ you need SYSTEM_VARIABLES_ADMIN or SUPER. The CONNECTION_ADMIN privilege is required to connect when super_read_only=ON.
  • Cloud-managed MySQL (RDS, Cloud SQL, Aurora): Managed replicas enforce read_only and super_read_only automatically. You cannot disable them on replica instances; use the primary endpoint for writes, or promote the replica.
  • Group Replication / InnoDB Cluster: Secondary nodes always run with super_read_only=ON. Only the primary node accepts writes, and this is managed automatically by the cluster.

Frequently Asked Questions

Why am I getting error 1036 only in production but not in development? Production environments commonly use a primary/replica architecture where application reads are load-balanced across replicas. If your application's connection pool is routing write queries to a replica, you will only see 1036 in production. Audit your database DSN configuration and ensure write operations use the primary/writer endpoint.

Can a user with SUPER privilege bypass read_only? Yes — on MySQL 5.7 and earlier, a SUPER user can write to tables even when read_only=ON. However, super_read_only=ON blocks even SUPER users. In MySQL 8.0+, SYSTEM_VARIABLES_ADMIN or CONNECTION_ADMIN is needed instead of SUPER.

Does error 1036 roll back an open transaction automatically? No. MySQL raises the error and rejects the offending statement, but the transaction remains open. Your application must explicitly issue ROLLBACK (or COMMIT if the prior work should be saved) to close the transaction.

Can an individual table be made read-only without making the whole server read-only? MySQL does not natively support per-table read-only flags via SQL (unlike PostgreSQL's ALTER TABLE ... ENABLE ROW LEVEL SECURITY patterns). You can approximate it by revoking INSERT, UPDATE, DELETE, and ALTER privileges on a specific table, which produces error 1142 rather than 1036. Some storage-engine-level file permission tricks can produce 1036 per table, but this is fragile and not recommended in production.

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.