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 fromvarchar(80)
tovarchar(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:
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:
- 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?
- request that
- When dealing with the original integration test timing out, how can I further diagnose the situation from MySQL side?