-- 1、查询是否锁表
SHOW OPEN TABLES WHERE In_use > 0;

-- 定位 DDL 被阻塞的问题
SELECT * FROM sys.schema_table_lock_waits ;
-- 2、查询进程
SHOW PROCESSLIST;

--  查询到相对应的进程===然后 
-- KILL    204;

slave_transaction_retries
-- 3. 查看正在锁的事务
/*
innodb_trx表:
trx_id:事务ID。
trx_state:事务状态,有以下几种状态:RUNNING、LOCK WAIT、ROLLING BACK 和 COMMITTING。
trx_started:事务开始时间。
trx_requested_lock_id:事务当前正在等待锁的标识,可以和 INNODB_LOCKS 表 JOIN 以得到更多详细信息。
trx_wait_started:事务开始等待的时间。
trx_weight:事务的权重。
trx_mysql_thread_id:事务线程 ID,可以和 PROCESSLIST 表 JOIN。
trx_query:事务正在执行的 SQL 语句。
trx_operation_state:事务当前操作状态。
trx_tables_in_use:当前事务执行的 SQL 中使用的表的个数。
trx_tables_locked:当前执行 SQL 的行锁数量。
trx_lock_structs:事务保留的锁数量。
trx_lock_memory_bytes:事务锁住的内存大小,单位为 BYTES。
trx_rows_locked:事务锁住的记录数。包含标记为 DELETED,并且已经保存到磁盘但对事务不可见的行。
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:是否立刻放弃为自适应散列索引搜索 LATCH 的标识。
*/
SELECT * FROM INFORMATION_SCHEMA.innodb_trx ;

/*
innodb_locks 表:
lock_id:锁 ID。
lock_trx_id:拥有锁的事务 ID。可以和 INNODB_TRX 表 JOIN 得到事务的详细信息。
lock_mode:锁的模式。有如下锁类型:行级锁包括:S、X、IS、IX,分别代表:共享锁、排它锁、意向共享锁、意向排它锁。表级锁包括:S_GAP、X_GAP、IS_GAP、IX_GAP 和 AUTO_INC,分别代表共享间隙锁、排它间隙锁、意向共享间隙锁、意向排它间隙锁和自动递增锁。
lock_type:锁的类型。RECORD 代表行级锁,TABLE 代表表级锁。
lock_table:被锁定的或者包含锁定记录的表的名称。
lock_index:当 LOCK_TYPE=’RECORD’ 时,表示索引的名称;否则为 NULL。
lock_space:当 LOCK_TYPE=’RECORD’ 时,表示锁定行的表空间 ID;否则为 NULL。
lock_page:当 LOCK_TYPE=’RECORD’ 时,表示锁定行的页号;否则为 NULL。
lock_rec:当 LOCK_TYPE=’RECORD’ 时,表示一堆页面中锁定行的数量,亦即被锁定的记录号;否则为 NULL。
lock_data:当 LOCK_TYPE=’RECORD’ 时,表示锁定行的主键;否则为NULL。
*/
SELECT * FROM INFORMATION_SCHEMA.innodb_locks;

/*
innodb_lock_waits 表:
requesting_trx_id:请求事务的 ID。
requested_lock_id:事务所等待的锁定的 ID。可以和 INNODB_LOCKS 表 JOIN。
blocking_trx_id:阻塞事务的 ID。
blocking_lock_id:某一事务的锁的 ID,该事务阻塞了另一事务的运行。可以和 INNODB_LOCKS 表 JOIN。
*/
SELECT * FROM INFORMATION_SCHEMA.innodb_lock_waits;

-- 生产 KILL 语句
SELECT concat('kill ', i.trx_mysql_thread_id, ';')
FROM information_schema.innodb_trx i, (
    SELECT MAX(time) AS max_time
    FROM information_schema.processlist
    WHERE state = 'Waiting for table metadata lock'
      AND (info LIKE 'alter%'
      OR info LIKE 'create%'
      OR info LIKE 'drop%'
      OR info LIKE 'truncate%'
      OR info LIKE 'rename%'
  )) p
WHERE timestampdiff(second, i.trx_started, now()) > p.max_time
;

/*
MySQL 5.7中使用sys.schema_table_lock_waits的注意事项
sys.schema_table_lock_waits 视图依赖了一张 MDL 相关的表-performance_schema.metadata_locks。

该表是 MySQL 5.7 引入的,会显示 MDL 的相关信息,包括作用对象、锁的类型及锁的状态等。

但在 MySQL 5.7 中,该表默认为空,因为与之相关的 instrument 默认没有开启。MySQL 8.0 才默认开启。

mysql> select * from performance_schema.setup_instruments where name='wait/lock/metadata/sql/mdl';
+----------------------------+---------+-------+
| NAME                       | ENABLED | TIMED |
+----------------------------+---------+-------+
| wait/lock/metadata/sql/mdl | NO      | NO    |
+----------------------------+---------+-------+
1 row in set (0.00 sec)
所以,在 MySQL 5.7 中,如果我们要使用 sys.schema_table_lock_waits ,必须首先开启 MDL 相关的 instrument。

开启方式很简单,直接修改 performance_schema.setup_instruments 表即可。

具体SQL如下。

UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME = 'wait/lock/metadata/sql/mdl';

但这种方式是临时生效,实例重启后,又会恢复为默认值。

建议同步修改配置文件。

[mysqld]
performance-schema-instrument='wait/lock/metadata/sql/mdl=ON'


1. 执行 show processlist ,如果 DDL 的状态是 Waiting for table metadata lock  ,则意味着这个 DDL 被阻塞了。

2. 定位导致 DDL 被阻塞的会话,常用的方法有两种:

sys.schema_table_lock_waits
SELECT sql_kill_blocking_connection
FROM sys.schema_table_lock_waits
WHERE blocking_lock_type <> 'SHARED_UPGRADABLE'
  AND (waiting_query LIKE 'alter%'
  OR waiting_query LIKE 'create%'
  OR waiting_query LIKE 'drop%'
  OR waiting_query LIKE 'truncate%'
  OR waiting_query LIKE 'rename%');
这种方法适用于 MySQL 5.7 和 8.0。

注意,MySQL 5.7 中,MDL 相关的 instrument 默认没有打开。

Kill DDL 之前的会话
SELECT concat('kill ', i.trx_mysql_thread_id, ';')
FROM information_schema.innodb_trx i, (
    SELECT MAX(time) AS max_time
    FROM information_schema.processlist
    WHERE state = 'Waiting for table metadata lock'
      AND (info LIKE 'alter%'
      OR info LIKE 'create%'
      OR info LIKE 'drop%'
      OR info LIKE 'truncate%'
      OR info LIKE 'rename%'
  )) p
WHERE timestampdiff(second, i.trx_started, now()) > p.max_time;
如果 MySQL 5.7 中 MDL 相关的 instrument 没有打开或在 MySQL 5.6 中,可使用该方法。

*/

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

-- 4.查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

-- 
-- show engine innodb status;

-- 5.查看实时会话
select id,
       user,
       host,
       db,
       command,
       time,
       state,
       info
  from information_schema.PROCESSLIST
 order by time desc;
 
 -- 6. 查看DDL阻塞的情况
 SELECT * FROM sys.schema_table_lock_waits 
 WHERE blocking_lock_type <> 'SHARED_UPGRADABLE';


-- 解析这段时间的binlog文件为SQL文件
-- binglog 日常查看
-- show master status;
/usr/bin/mysqlbinlog --no-defaults --database=zhxx_six_mes  --base64-output=decode-rows -v --start-datetime='2022-02-28 20:00:00' --stop-datetime='2022-02-28 21:00:00'  /home/mysql/data/mysql/master-bin.000036 | more

-- binglog 
-- 存储到可用脚本 
/usr/bin/mysqlbinlog --no-defaults --database=zhxx_six_mes  --base64-output=decode-rows -v --start-datetime='2022-02-28 20:00:00' --stop-datetime='2022-02-28 21:00:00'  /home/mysql/data/mysql/master-bin.000036 >/tmp/binlog20220228.sql

-- 同步日志查看:
[root@localhost ~]# /usr/bin/mysqlbinlog --no-defaults --database=zhxx_six_mes  --base64-output=decode-rows -v  --start-datetime='2022-02-17 00:00:00' --stop-datetime='2022-02-18 15:00:00' /home/mysql/data/mysql/relay-log.000002 >/tmp/relay-log20220218.sql


-- 四、临时表 
mysql> show global status like 'created_tmp%'; 
+-------------------------+---------+ 
| Variable_name | Value | 
+-------------------------+---------+ 
| Created_tmp_disk_tables | 21197 | 
| Created_tmp_files | 58 | 
| Created_tmp_tables | 1771587 | 
+-------------------------+---------+  

 -- 每次创建临时表,Created_tmp_tables增加,如果是在磁盘上创建临时表,Created_tmp_disk_tables也增加,Created_tmp_files表示MySQL服务创建的临时文件文件数,比较理想的配置是:
Created_tmp_disk_tables / Created_tmp_tables * 100% <= 25% 
-- 比如上面的服务器Created_tmp_disk_tables / Created_tmp_tables * 100% = 1.20%,应该相当好了。我们再看一下MySQL服务器对临时表的配置: 
mysql> show variables where Variable_name in ('tmp_table_size', 'max_heap_table_size'); 
+---------------------+-----------+ 
| Variable_name | Value | 
+---------------------+-----------+ 
| max_heap_table_size | 268435456 | 
| tmp_table_size | 536870912 | 
+---------------------+-----------+  

-- 只有256MB以下的临时表才能全部放内存,超过的就会用到硬盘临时表。
    

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐