Mysql DDL-запрос застрял в ожидании блокировки таблицы метаданных при переносе в транзакции - PullRequest
2 голосов
/ 07 апреля 2019

Это случайное поведение (не повторяющееся после перезапуска сеанса mysql), когда я заключаю запрос DDL в транзакцию T1 и одновременно инициирую другую транзакцию T2 с запросом select для той же таблицы, DDLзапрос застревает в ожидании ожидаемой блокировки метаданных таблицы, а любые другие запросы select ожидают завершения DDL-запроса.Но после фиксации T2 DDL должен получить и завершить блокировку метаданных, но он все еще ожидает состояние блокировки метаданных таблицы.

Запрос подключения 1:

mysql> begin;                            
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE merchants ADD COLUMN temp6 varchar(255);

Запрос соединения 2:

mysql> begin;                            
Query OK, 0 rows affected (0.00 sec)

mysql> select * from merchants where account_id=null;
Empty set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

Последовательность запросов:

  1. Соединение 1: начало;
  2. Соединение 2: начало;
  3. Соединение 2: выберите * из торговцев, где account_id = null;
  4. Соединение 1: продавцы ALTER TABLE ADD COLUMN temp6 varchar (255);
  5. Соединение2: commit;
Server version: 8.0.13 MySQL Community Server - GPL

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)

mysql> SELECT 
    OBJECT_TYPE, 
    OBJECT_SCHEMA, 
    OBJECT_NAME, 
    LOCK_TYPE, 
    LOCK_STATUS, 
    THREAD_ID, 
    PROCESSLIST_ID, 
    PROCESSLIST_INFO 
FROM performance_schema.metadata_locks 
INNER JOIN performance_schema.threads ON THREAD_ID = OWNER_THREAD_ID 
WHERE PROCESSLIST_ID <> CONNECTION_ID();
+-------------+-------------------------+-----------------------------------+---------------------+-------------+-----------+----------------+-----------------------------------------------------+
| OBJECT_TYPE | OBJECT_SCHEMA           | OBJECT_NAME                       | LOCK_TYPE           | LOCK_STATUS | THREAD_ID | PROCESSLIST_ID | PROCESSLIST_INFO                                    |
+-------------+-------------------------+-----------------------------------+---------------------+-------------+-----------+----------------+-----------------------------------------------------+
| GLOBAL      | NULL                    | NULL                              | INTENTION_EXCLUSIVE | GRANTED     |       126 |             87 | ALTER TABLE merchants ADD COLUMN temp6 varchar(255) |
| SCHEMA      | merchant_onboarding_dev | NULL                              | INTENTION_EXCLUSIVE | GRANTED     |       126 |             87 | ALTER TABLE merchants ADD COLUMN temp6 varchar(255) |
| TABLE       | merchant_onboarding_dev | merchants                         | SHARED_UPGRADABLE   | GRANTED     |       126 |             87 | ALTER TABLE merchants ADD COLUMN temp6 varchar(255) |
| BACKUP LOCK | NULL                    | NULL                              | INTENTION_EXCLUSIVE | GRANTED     |       126 |             87 | ALTER TABLE merchants ADD COLUMN temp6 varchar(255) |
| TABLESPACE  | NULL                    | merchant_onboarding_dev/merchants | INTENTION_EXCLUSIVE | GRANTED     |       126 |             87 | ALTER TABLE merchants ADD COLUMN temp6 varchar(255) |
| TABLE       | merchant_onboarding_dev | #sql-63_57                        | EXCLUSIVE           | GRANTED     |       126 |             87 | ALTER TABLE merchants ADD COLUMN temp6 varchar(255) |
| TABLE       | merchant_onboarding_dev | merchants                         | EXCLUSIVE           | PENDING     |       126 |             87 | ALTER TABLE merchants ADD COLUMN temp6 varchar(255) |
+-------------+-------------------------+-----------------------------------+---------------------+-------------+-----------+----------------+-----------------------------------------------------+
7 rows in set (0.00 sec)

mysql> show full processlist;
+----+-----------------+-----------------+-------------------------+---------+--------+---------------------------------+-----------------------------------------------------+
| Id | User            | Host            | db                      | Command | Time   | State                           | Info                                                |
+----+-----------------+-----------------+-------------------------+---------+--------+---------------------------------+-----------------------------------------------------+
|  4 | event_scheduler | localhost       | NULL                    | Daemon  | 115824 | Waiting on empty queue          | NULL                                                |
| 62 | root            | localhost:59116 | merchant_onboarding_dev | Sleep   |    107 |                                 | NULL                                                |
| 63 | root            | localhost:59117 | merchant_onboarding_dev | Sleep   |    107 |                                 | NULL                                                |
| 65 | root            | localhost:59119 | NULL                    | Sleep   |      1 |                                 | NULL                                                |
| 79 | root            | localhost       | merchant_onboarding_dev | Query   |      0 | starting                        | show full processlist                               |
| 81 | root            | localhost       | merchant_onboarding_dev | Sleep   |    838 |                                 | NULL                                                |
| 83 | root            | localhost       | merchant_onboarding_dev | Sleep   |    821 |                                 | NULL                                                |
| 87 | root            | localhost       | merchant_onboarding_dev | Query   |    842 | Waiting for table metadata lock | ALTER TABLE merchants ADD COLUMN temp6 varchar(255) |
+----+-----------------+-----------------+-------------------------+---------+--------+---------------------------------+-----------------------------------------------------+
8 rows in set (0.00 sec)

mysql> SHOW ENGINE INNODB STATUS;

=====================================
2019-04-08 02:30:45 0x700006ef3000 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 20 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 242 srv_active, 0 srv_shutdown, 73418 srv_idle
srv_master_thread log flush and writes: 0
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 87
OS WAIT ARRAY INFO: signal count 516
RW-shared spins 722, rounds 723, OS waits 1
RW-excl spins 1110, rounds 3537, OS waits 28
RW-sx spins 0, rounds 0, OS waits 0
Spin rounds per wait: 1.00 RW-shared, 3.19 RW-excl, 0.00 RW-sx
------------
TRANSACTIONS
------------
Trx id counter 15753
Purge done for trx's n:o < 15749 undo n:o < 0 state: running but idle
History list length 11
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 281479647891952, not started
mysql tables in use 1, locked 1
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 281479647891040, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 281479647893776, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 281479647892864, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 281479647890128, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 281479647889216, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (read thread)
I/O thread 4 state: waiting for i/o request (read thread)
I/O thread 5 state: waiting for i/o request (read thread)
I/O thread 6 state: waiting for i/o request (write thread)
I/O thread 7 state: waiting for i/o request (write thread)
I/O thread 8 state: waiting for i/o request (write thread)
I/O thread 9 state: waiting for i/o request (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
 ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
950 OS file reads, 52924 OS file writes, 40911 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
 insert 0, delete mark 0, delete 0
discarded operations:
 insert 0, delete mark 0, delete 0
Hash table size 34679, node heap has 3 buffer(s)
Hash table size 34679, node heap has 3 buffer(s)
Hash table size 34679, node heap has 7 buffer(s)
Hash table size 34679, node heap has 2 buffer(s)
Hash table size 34679, node heap has 2 buffer(s)
Hash table size 34679, node heap has 1 buffer(s)
Hash table size 34679, node heap has 2 buffer(s)
Hash table size 34679, node heap has 4 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
---
LOG
---
Log sequence number          89894761
Log buffer assigned up to    89894761
Log buffer completed up to   89894761
Log written up to            89894761
Log flushed up to            89894761
Added dirty pages up to      89894761
Pages flushed up to          89894761
Last checkpoint at           89894761
42886 log i/o's done, 0.00 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 1037251
Buffer pool size   8191
Free buffers       3332
Database pages     4835
Old database pages 1764
Modified db pages  0
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 634, not young 1
0.00 youngs/s, 0.00 non-youngs/s
Pages read 911, created 3927, written 8771
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 4835, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
0 read views open inside InnoDB
Process ID=99, Main thread ID=0x700006689000 , state=sleeping
Number of rows inserted 176434, updated 4249, deleted 10814, read 2383183
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================

Я не могу понять, почему DDL-запрос продолжает ожидать блокировки метаданных таблицы, даже если транзакция, которая удерживала блокировку, фиксируется.

1 Ответ

2 голосов
/ 08 апреля 2019

В MySQL большинство операторов DDL фактически генерируют неявный коммит .ALTER TABLE оператор попадает в эту категорию.Начиная с документации :

Операторы, перечисленные в этом разделе (и любые синонимы для них), неявно завершают любую транзакцию, активную в текущем сеансе, как если бы вы выполняли COMMIT ранеевыполнение оператора.

Большинство этих операторов также вызывают неявную фиксацию после выполнения.

Эта внутренняя документация содержит более подробную информацию ... и некоторые вещи могут запутаться:

Кроме того, некоторые операторы DDL вызывают временную транзакциюcommitits: например, ALTER TABLE выдает коммит после копирования данных из исходной таблицы во внутреннюю временную таблицу.

Поэтому, пока вы выполняете ALTER TABLE, MySQL неявно пытается зафиксировать внутри оператора, но не может, так как выполняется другая транзакция.Документация точно не покрывает этот вариант использования, но я подозреваю, что сервер неправильно обрабатывает эту ситуацию и генерирует странное поведение, которое вы видите.В самой документации утверждается, что этот тип поведения плохо определен .

Итог: вы не можете полагаться на транзакции для обработки параллелизма при выполнении оператора ALTER TABLE.Как следствие, вы не хотите ALTER таблицы, когда она занята другой транзакцией: это небезопасно.Перед выполнением такого оператора вы хотите убедиться, что для таблицы не установлена ​​блокировка.Да, это, безусловно, влечет за собой болезненные ограничения при работе с производственными базами данных, но похоже, что именно так MySQL делает это ...

...