MySQL hangs on ALTER TABLE - mysql

My not-so-big table hangs on an ALTER command. What could it be?
Only 150k rows, 42 fields 142 MByte total. InnoDB storage engine and Server version: 5.5.44-MariaDB MariaDB Server. 1 field, 'slotindex', is primary key: bigint(20) and BTREE type.
The command:
MariaDB [mydb]> ALTER TABLE `runs` CHANGE `p_w_trans_x` `p_w_tran_x` FLOAT NOT NULL;
Stage: 1 of 2 'copy to tmp table' 65.7% of stage done
Stage: 2 of 2 'Enabling keys' 0% of stage done
Will completely hang forever in this stage 2.
The processlist is then as follows:
MariaDB [(none)]> show full processlist;
+--------+------+-----------------+-----------+---------+-------+---------------------------------+---------------------------------------------------------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+--------+------+-----------------+-----------+---------+-------+---------------------------------+---------------------------------------------------------------------+----------+
| 274226 | root | localhost:45423 | edc_proxy | Sleep | 16043 | | NULL | 0.000 |
| 274319 | root | localhost | myDB | Query | 99 | Waiting for table metadata lock | ALTER TABLE `runs` CHANGE `p_w_trans_x` `p_w_tran_x` FLOAT NOT NULL | 0.000 |
| 274416 | root | localhost | NULL | Query | 0 | NULL | show full processlist | 0.000 |
+--------+------+-----------------+-----------+---------+-------+---------------------------------+---------------------------------------------------------------------+----------+
This answer suggests checking the information_schema tables, not much there:
MariaDB [INFORMATION_SCHEMA]> SELECT * FROM INNODB_LOCK_WAITS;
Empty set (0.00 sec)
MariaDB [INFORMATION_SCHEMA]> SELECT * FROM INNODB_LOCKS ;
Empty set (0.00 sec)
MariaDB [INFORMATION_SCHEMA]> SELECT * FROM INNODB_TRX;
+----------+-----------+---------------------+-----------------------+------------------+------------+---------------------+-----------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+---------------------------+
| trx_id | trx_state | trx_started | trx_requested_lock_id | trx_wait_started | trx_weight | trx_mysql_thread_id | trx_query | trx_operation_state | trx_tables_in_use | trx_tables_locked | trx_lock_structs | trx_lock_memory_bytes | trx_rows_locked | trx_rows_modified | trx_concurrency_tickets | trx_isolation_level | trx_unique_checks | trx_foreign_key_checks | trx_last_foreign_key_error | trx_adaptive_hash_latched | trx_adaptive_hash_timeout |
+----------+-----------+---------------------+-----------------------+------------------+------------+---------------------+-----------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+---------------------------+
| 83A8B36E | RUNNING | 2016-12-08 11:13:02 | NULL | NULL | 0 | 274226 | NULL | NULL | 0 | 0 | 0 | 376 | 0 | 0 | 0 | REPEATABLE READ | 1 | 1 | NULL | 0 | 10000 |
+----------+-----------+---------------------+-----------------------+------------------+------------+---------------------+-----------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+---------------------------+
1 row in set (0.00 sec)
And the section on transactions from show engine innodb status;:
------------
TRANSACTIONS
------------
Trx id counter 83A8F071
Purge done for trx's n:o < 83A8CA86 undo n:o < 0
History list length 1490
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0, not started
MySQL thread id 274543, OS thread handle 0x7fbb863e6700, query id 85356480 localhost root
show engine innodb status
---TRANSACTION 83A8EB07, not started
mysql tables in use 1, locked 2
MySQL thread id 274542, OS thread handle 0x7fbb843f6700, query id 85354935 localhost root Waiting for table metadata lock
ALTER TABLE `runs` CHANGE `p_w_trans_x` `p_w_tran_x` FLOAT NOT NULL
---TRANSACTION 83A8B36E, ACTIVE 24627 sec
MySQL thread id 274226, OS thread handle 0x7fbb845f5700, query id 85337236 localhost 127.0.0.1 root
Trx read view will not see trx with id >= 83A8B36F, sees < 83A8B36D
----------------------------
END OF INNODB MONITOR OUTPUT
============================
Any pointers for further investigation, for circumventing the problem and for solving are appreciated!

A metadata lock is an implicit (from the user perspective) lock that prevents DDL against the table because something else needs the table to remain in its current form. In this case, it's a transaction that has been left running.
Task 1: Your alter will succeed if you kill the connection on thread 274226.
mysql> KILL 274226;
The problem here, as indicated by information_schema.innodb_trx, is that this thread has left a transaction running for several hours and we can infer that this table has been referenced by that transaction. A table can't be altered until no transactioms still have an MVCC view or any locks involving the table. This transaction holds a view, which we can again infer could impact this table, as shown in the last line:
--TRANSACTION 83A8B36E, ACTIVE 24627 sec
MySQL thread id 274226, OS thread handle 0x7fbb845f5700, query id 85337236 localhost 127.0.0.1 root
Trx read view will not see trx with id >= 83A8B36F, sees < 83A8B36D
Note that Sleep is not a real command, in this context, it's just the placeholder status for any idle connection. All connections are doing something, and in this case the "something" is sleeping -- in other words, idle and waiting for another query. But an idle connection is still a connection, and if your code (or query browser tool) leaves a transaction running, it just keeps running.
Task 2: find the bug or mistake that left that transaction running. In a live application, leaving transactions running potentially make a much bigger mess.

I was having a very similar issue with table lock, but it ended up being MySQL Workbench out of all things. Any RENAME TABLE or ALTER TABLE command in MySQL Workbench would just sit claiming a meta lock. I logged onto the server and was able to execute those types of queries no problem. Current version of Workbench is 8.0.22.
I had sifted through all these queries and was totally stumped when they showed no issues:
SHOW OPEN TABLES;
SHOW ENGINE inndodb STATUS;
SELECT * FROM INNODB_LOCK_WAITS;
SELECT * FROM INNODB_LOCKS;
SELECT * FROM INNODB_TRX;
SHOW FULL PROCESSLIST;

Related

MySQL Alter Table DB Freezes

I'm using Ubuntu 16.04.3 and mysql Ver 14.14 Distrib 5.7.22.
When I try to alter my db table column with the following command the database appears to freeze;
mysql> alter table records modify column name varchar(150);
Table size is 2.8MiB (6,000 records).
I'm simply trying to change the varchar(150) part.
I have tried to do the same thing in GUI programs such as HeidiSQL and Workbench, same result - program crashes and I have to restart the session.
I am logged into the db and server as root. I checked the /var/log/mysql/error.log but it only displays failed login attempts, nothing relevant to this error.
Any ideas what's going on or how I can troubleshoot this?
Do you have any apps running long-running transactions against this table? If there are any transactions holding a metadata lock, it won't be able to start the ALTER TABLE.
If you can run SHOW PROCESSLIST in another window while the ALTER TABLE appears to hang, it might show "waiting for metadata lock".
+----+------+-----------+------+---------+------+---------------------------------+------------------------+-----------+---------------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined |
+----+------+-----------+------+---------+------+---------------------------------+------------------------+-----------+---------------+
| 4 | root | localhost | test | Query | 0 | init | show processlist | 0 | 0 |
| 5 | root | localhost | test | Query | 15 | Waiting for table metadata lock | alter table foo... | 0 | 0 |
+----+------+-----------+------+---------+------+---------------------------------+------------------------+-----------+---------------+
Then you need to figure out which app has an open transaction that is blocking the ALTER TABLE, and get that app to finish its transaction, or else kill the transaction.

Lock wait timeout exceeded in MySQL

I get the following error:
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
I did the
show processlist;
command and killed all the processes and well run the command
+------+------+-----------+-------------------+---------+------+-----------+---------------------------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+------+------+-----------+-------------------+---------+------+-----------+---------------------------------------------------------------------------------+
| 1749 | cyee | localhost | CY_Test | Killed | 2308 | query end | INSERT INTO CY_Test.patient2010 SELECT * FROM cmsdata-outpatient-2010.patient |
| 1755 | cyee | localhost | cmsdata-inpatient | Query | 0 | NULL | SHOW FULL PROCESSLIST |
+------+------+-----------+-------------------+---------+------+-----------+---------------------------------------------------------------------------------+
set innodb_lock_wait_timeout=1000;
that another site suggested, but i still get the same error. Any help would be appreciated, thanks!
You can set variable innodb_lock_wait_timeout=100 for lock time to 100 sec.
mysql> set innodb_lock_wait_timeout=100
Query OK, 0 rows affected (0.02 sec)
mysql> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 100 |
+--------------------------+-------+
The transaction which is timeout, try to lock table which is hold by another process. and your timeout variable set with little number of second. so it shows error.
You can see more status by the command.
SHOW ENGINE INNODB STATUS\G
You can see list of locked tables by-
show open tables where in_use>0;
Now see the thread which is using this table
show full processlist;
now you can kill that thread or wait to complete it.

MySQL 5.5 metadata lock delays table drop

I was doing some tests with table compression and killed a large (138M rows) insert. I went to drop the table this morning and it's taking a very long time. I checked the process list
| 39 | root | localhost | cdr3 | Killed | 72959 | query end | insert into cdr3_test_4 select * from cdr3_v1 |
| 44 | root | localhost | cdr3 | Query | 2005 | Waiting for table metadata lock | drop table cdr3_test_4 |
| 45 | root | localhost | cdr3 | Query | 0 | NULL | show processlist |
and the InnoDB engine status
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0, not started
MySQL thread id 45, OS thread handle 0x7fa3da748700, query id 170 localhost root
show engine innodb status
---TRANSACTION 0, not started
MySQL thread id 44, OS thread handle 0x7fa3da849700, query id 149 localhost root Waiting for table metadata lock
drop table cdr3_test_4
---TRANSACTION 3C05, ACTIVE 72922 sec rollback
mysql tables in use 2, locked 2
ROLLING BACK 165436 lock struct(s), heap size 26458552, 96615068 row lock(s), undo log entries 56851106
MySQL thread id 39, OS thread handle 0x7fa3da94a700, query id 131 localhost root query end
insert into cdr3_test_4 select * from cdr3_v1
How do I interpret this? Will the drop occur when the rollback is complete? I tried to kill it within mysql by thread ID and query ID and the server couldn't find it. Is there a better way to kill it? If I kill it will it just start over?
Thanks
Mike

How to kill a thread in PHPmyadmin

I have a thread showing in PHPmyadmin under processes. However, when I click kill, I get the error:
phpMyAdmin was unable to kill thread 148. It probably has already been closed.
Why does this thread still then show as active? How can I remove it entirely?
Open mysql client and type
mysql> show processlist;
+-----+------+-----------+------+---------+------+-------+------------------+-----------+---------------+-----------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined | Rows_read |
+-----+------+-----------+------+---------+------+-------+------------------+-----------+---------------+-----------+
| 106 | root | localhost | NULL | Query | 0 | NULL | show processlist | 0 | 0 | 0 |
+-----+------+-----------+------+---------+------+-------+------------------+-----------+---------------+-----------+
1 row in set (0.00 sec)
you'll see processes with ID, than you can do this:
mysql> kill 106;
and your process (id = 106) will be killed.
Between the time that phpMyAdmin received the list of processes and the time you clicked to kill one of them, this process had finished by itself.
See also https://sourceforge.net/p/phpmyadmin/feature-requests/1490/.
This phenomenon is caused by the connection used to access PHPmyadmin itself, hence it doesn't show on the direct MySQLQuery. It can't be killed, as it would close the PHPmyadmin connection.

MySQL query not going away after being killed

I have a MySQL query that is copying data from one table to another for processing. For some reason, this query that normally takes a few seconds locked up overnight and ran for several hours. When I logged in this morning, I tried to kill the query, but it is still listed in the process list.
| Id | User | Host | db | Command | Time | State | Info |
+---------+----------+-----------+------+---------+-------+--------------+--------------------------------------------------------------------------------------+
| 1061763 | tb_admin | localhost | dw | Killed | 45299 | Sending data | INSERT INTO email_data_inno_stage SELECT * FROM email_data_test LIMIT 4480000, 10000 |
| 1062614 | tb_admin | localhost | dw | Killed | 863 | Sending data | INSERT INTO email_data_inno_stage SELECT * FROM email_data_test LIMIT 4480000, 10000 |
What could have caused this, and how can I kill this process so I can get on with my work?
If the table email_data_test is MyISAM and it was locked, that would have held up the the INSERT.
If the table email_data_test is InnoDB, then a lot of MVCC data was being written in ib_logfiles, which may not have occurred yet.
In both cases, you had the LIMIT clause scroll through 4,480,000 rows just to get to 10,000 rows you actually needed to INSERT.
Killing the query only causes the InnoDB table email_data_inno_stage to execute a rollback.