Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL failing to ALTER TABLE which is being actively written to

In one of the use cases of my application, I have two concurrent MySQL connections:

  • one actively writing to a table named T (actually, continuously updating a single row in this table), and
  • another one executing a DDL against the very same table (ALTER TABLE, adding 8 new columns and extending one column from varchar(80) to varchar(2000)). The DDL is expected to eventually complete.

The columns in the UPDATE DML are not affected by the DDL.

The table contains only a single row (the one being UPDATE'd).

Analysis

What I observe when an integration test covering this use case is run is a test time out (the table is being so actively written to, so that the DDL never completes), but only for MySQL 5.7. Normally, the test is expected to complete in under 30 seconds on our hardware (which indeed happens for MySQL 5.6 and 8.0), but for MySQL 5.7 even 200 seconds is not sufficient. I have experimented with different ALGORITHM and LOCK values (see 13.1.8 ALTER TABLE Syntax), with no luck.

When I profile my application (MySQL 5.7 case), I observe that 99% of CPU time is spent reading from a socket (i. e. waiting for MySQL to respond that the table has been altered), but the database instance is a sort of a black box to me -- of course I have performance_schema enabled and can run queries against it, but I have no idea which exact information I am looking for.

Synthesis

At the same time, I failed to reduce the problem to a minimal self-contained unit test -- the only thing I observe is 3x to 10x increase in test elapsed time for MySQL 5.7 compared to other MySQL versions, but the DDL doesn't hang forever:

enter image description here

All MySQL versions are either stock versions for Windows or Debian Linux downloaded from www.mysql.com with minimal changes to my.cnf, or the official Docker images.

Questions:

  1. Is it indeed technically possible for MySQL to delay the execution of ALTER TABLE DDL forever? Or what I'm observing is just a very busy database instance? Is it possible to either
    • request that ALTER TABLE is executed interruptibly, i. e. an error is returned by the database if a certain time-out is exceeded, or
    • force all other connections which can potentially place even a SHARED lock on the table or some of its rows to pause, so that they don't intervene while the DDL is being executed?
  2. When dealing with the original integration test timing out, how can I further diagnose the situation from MySQL side?
like image 660
Bass Avatar asked Aug 17 '18 20:08

Bass


People also ask

Why ALTER TABLE is not working in MySQL?

If you get a duplicate-key error when using ALTER TABLE to change the character set or collation of a character column, the cause is either that the new column collation maps two keys to the same value or that the table is corrupted. In the latter case, you should run REPAIR TABLE on the table.

How do I remove a foreign key from a column in MySQL?

You can drop a foreign key constraint using the following ALTER TABLE syntax: ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol; If the FOREIGN KEY clause defined a CONSTRAINT name when you created the constraint, you can refer to that name to drop the foreign key constraint.

How do I edit a table in MySQL?

You can add or modify the columns or indexes of a table, change the engine, add foreign keys, or alter the table name. To access the MySQL Table Editor, right-click a table name in the Navigator area of the sidebar with the Schemas secondary tab selected and click Alter Table.

What is the use of ALTER TABLE in MySQL?

Introduction to Alter Table Mysql In MySQL, ALTER TABLE command is used to change the name of the table or rename one or more columns of the table, add new columns, remove existing ones, modify the datatype, length, index of one or more column and we can also rename the name of the table.

How to modify the column in a mySQL table?

We can modify the column by changing its definition and position by using the ALTER TABLE statement with MODIFY command. The syntax of modifying the column is similar to adding the column which is as follows –

How to rename a table in MySQL?

First, specify the name of the table that you want to rename after the ALTER TABLE keywords. Second, specify the new name for the table after the RENAME TO keywords. In this tutorial, you have learned how to use the MySQL ALTER TABLE statement to add a column, modify a column, rename a column, drop a column and rename a table.

What is the ALTER TABLE statement used for?

The ALTER TABLE statement is also used to add and drop various constraints on an existing table. To delete a column in a table, use the following syntax (notice that some database systems don't allow deleting a column):


1 Answers

TL;DR — commit your transactions to unblock your ALTER TABLE.


Yes, ALTER TABLE can block for a long time. It may seem like forever. It's actually the value of lock_wait_timeout, which is 31536000 seconds by default, or 365 days.

In MySQL, DDL statements like ALTER TABLE require an exclusive metadata lock on the table. The purpose is to make sure you don't ALTER TABLE from two concurrent sessions at the same time.

DML statement like SELECT, INSERT, UPDATE, DELETE also hold "shared" metadata locks. Shared locks can be held by multiple sessions concurrently, but block exclusive locks, because exclusive locks require that they be the only one to hold any type of lock on the table.

Documentation states:

This locking approach has the implication that a table that is being used by a transaction within one session cannot be used in DDL statements by other sessions until the transaction ends.

The purpose of DML statements holding a metadata lock is so they can preserve their repeatable-read view of the table without worry that another session is doing DROP TABLE or ALTER TABLE to compromise their view of the table. This locking is necessary because MySQL does not have versioned metadata (they are gradually working toward that).

This means a transaction that has run a simple SELECT and doesn't commit will block a DROP TABLE or ALTER TABLE that requires a locking change.

There is some nuance with the introduction of online DDL.

Online DDL Performance and Concurrency describes in more detail that an ALTER TABLE starts out by acquiring a shared metadata lock, so the uncommitted transaction will not block it. But the next phase may upgrade the shared metadata lock to an exclusive metadata lock, if the nature of the ALTER TABLE change requires it. At this point, the lock acquisition is blocked because the other transaction still holds its own metadata lock.

Online DDL doesn't apply to every type of ALTER TABLE operation; some still require exclusive locks. Changing a data type, for example, as you are doing, requires an exclusive lock. See Online DDL Overview for details.

like image 77
Bill Karwin Avatar answered Sep 23 '22 14:09

Bill Karwin