在上一篇《等待事件统计视图 | 全方位认识 sys 系统库》中,我们介绍了sys 系统库中的等待事件统计视图,本期的内容先给大家介绍会话信息和锁等待信息查询视图,通过这些视图我们可以清晰地知道每个会话正在做什么事情,是否存在锁等待。下面请跟随我们一起开始 sys 系统库的系统学习之旅吧~
PS:由于本文中所提及的视图功能的特殊性(DBA日常工作中除了排查慢SQL之外,另外一个可能需要占用大量精力的地方可能就是锁问题分析),所以下文中会列出相应视图中的select语句文本,以便大家更直观地学习它们。
InnoDB当前锁等待信息,默认按照发生锁等待的开始时间升序排序--wait_started字段即innodb_trx表的trx_wait_started字段。数据来源:information_schema的innodb_trx、innodb_locks、innodb_lock_waits(注:在8.0及其之后的版本中,该视图的信息来源为information_schema的innodb_trx、performance_schema的data_locks和data_lock_waits)
视图查询语句文本
# 不带x$前缀的视图的查询语句
SELECT r.trx_wait_started AS wait_started,
TIMEDIFF(NOW(), r.trx_wait_started) AS wait_age,
TIMESTAMPDIFF(SECOND, r.trx_wait_started, NOW()) AS wait_age_secs,
rl.lock_table AS locked_table,
rl.lock_index AS locked_index,
rl.lock_type AS locked_type,
r.trx_id AS waiting_trx_id,
r.trx_started as waiting_trx_started,
TIMEDIFF(NOW(), r.trx_started) AS waiting_trx_age,
r.trx_rows_locked AS waiting_trx_rows_locked,
r.trx_rows_modified AS waiting_trx_rows_modified,
r.trx_mysql_thread_id AS waiting_pid,
sys.format_statement(r.trx_query) AS waiting_query,
rl.lock_id AS waiting_lock_id,
rl.lock_mode AS waiting_lock_mode,
b.trx_id AS blocking_trx_id,
b.trx_mysql_thread_id AS blocking_pid,
sys.format_statement(b.trx_query) AS blocking_query,
bl.lock_id AS blocking_lock_id,
bl.lock_mode AS blocking_lock_mode,
b.trx_started AS blocking_trx_started,
TIMEDIFF(NOW(), b.trx_started) AS blocking_trx_age,
b.trx_rows_locked AS blocking_trx_rows_locked,
b.trx_rows_modified AS blocking_trx_rows_modified,
CONCAT('KILL QUERY ', b.trx_mysql_thread_id) AS sql_kill_blocking_query,
CONCAT('KILL ', b.trx_mysql_thread_id) AS sql_kill_blocking_connection
FROM information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id
INNER JOIN information_schema.innodb_locks bl ON bl.lock_id = w.blocking_lock_id
INNER JOIN information_schema.innodb_locks rl ON rl.lock_id = w.requested_lock_id
ORDER BY r.trx_wait_started;
# x$innodb_lock_waits:在8.0之前的版本,两者无区别
下面我们看看使用该视图查询返回的结果
# 不带x$前缀的视图
root@localhost : sys 12:41:45> select * from innodb_lock_waits\G;
*************************** 1. row ***************************
wait_started: 2017-09-07 00:42:32
wait_age: 00:00:12
wait_age_secs: 12
locked_table: `luoxiaobo`.`test`
locked_index: GEN_CLUST_INDEX
locked_type: RECORD
waiting_trx_id: 66823
waiting_trx_started: 2017-09-07 00:42:32
waiting_trx_age: 00:00:12
waiting_trx_rows_locked: 1
waiting_trx_rows_modified: 0
waiting_pid: 7
waiting_query: select * from test limit 1 for update
waiting_lock_id: 66823:106:3:2
waiting_lock_mode: X
blocking_trx_id: 66822
blocking_pid: 6
blocking_query: NULL
blocking_lock_id: 66822:106:3:2
blocking_lock_mode: X
blocking_trx_started: 2017-09-07 00:42:19
blocking_trx_age: 00:00:25
blocking_trx_rows_locked: 1
blocking_trx_rows_modified: 0
sql_kill_blocking_query: KILL QUERY 6
sql_kill_blocking_connection: KILL 6
1 row in set, 3 warnings (0.00 sec)
视图字段含义如下:
PS:8.0中废弃information_schema.innodb_locks和information_schema.innodb_lock_waits,迁移到performance_schema.data_locks和performance_schema.data_lock_waits,详见链接:
https://dev.mysql.com/doc/refman/8.0/en/data-locks-table.html
https://dev.mysql.com/doc/refman/8.0/en/data-lock-waits-table.html
包含所有前台和后台线程的processlist信息,默认按照进程等待时间和最近一个语句执行完成的时间降序排序。数据来源:performance_schema的threads、events_waits_current、events_statements_current、events_stages_current 、events_transactions_current 、session_connect_attrs表和 sys 系统库的 x$memory_by_thread_by_current_bytess视图
视图查询语句文本
# 不带x$前缀的视图
SELECT pps.thread_id AS thd_id,
pps.processlist_id AS conn_id,
IF(pps.name = 'thread/sql/one_connection',
CONCAT(pps.processlist_user, '@', pps.processlist_host),
REPLACE(pps.name, 'thread/', '')) user,
pps.processlist_db AS db,
pps.processlist_command AS command,
pps.processlist_state AS state,
pps.processlist_time AS time,
sys.format_statement(pps.processlist_info) AS current_statement,
IF(esc.end_event_id IS NULL,
sys.format_time(esc.timer_wait),
NULL) AS statement_latency,
IF(esc.end_event_id IS NULL,
ROUND(100 * (estc.work_completed / estc.work_estimated), 2),
NULL) AS progress,
sys.format_time(esc.lock_time) AS lock_latency,
esc.rows_examined AS rows_examined,
esc.rows_sent AS rows_sent,
esc.rows_affected AS rows_affected,
esc.created_tmp_tables AS tmp_tables,
esc.created_tmp_disk_tables AS tmp_disk_tables,
IF(esc.no_good_index_used > 0 OR esc.no_index_used > 0, 'YES', 'NO') AS full_scan,
IF(esc.end_event_id IS NOT NULL,
sys.format_statement(esc.sql_text),
NULL) AS last_statement,
IF(esc.end_event_id IS NOT NULL,
sys.format_time(esc.timer_wait),
NULL) AS last_statement_latency,
sys.format_bytes(mem.current_allocated) AS current_memory,
ewc.event_name AS last_wait,
IF(ewc.end_event_id IS NULL AND ewc.event_name IS NOT NULL,
'Still Waiting',
sys.format_time(ewc.timer_wait)) last_wait_latency,
ewc.source,
sys.format_time(etc.timer_wait) AS trx_latency,
etc.state AS trx_state,
etc.autocommit AS trx_autocommit,
conattr_pid.attr_value as pid,
conattr_progname.attr_value as program_name
FROM performance_schema.threads AS pps
LEFT JOIN performance_schema.events_waits_current AS ewc USING (thread_id)
LEFT JOIN performance_schema.events_stages_current AS estc USING (thread_id)
LEFT JOIN performance_schema.events_statements_current AS esc USING (thread_id)
LEFT JOIN performance_schema.events_transactions_current AS etc USING (thread_id)
LEFT JOIN sys.x$memory_by_thread_by_current_bytes AS mem USING (thread_id)
LEFT JOIN performance_schema.session_connect_attrs AS conattr_pid
ON conattr_pid.processlist_id=pps.processlist_id and conattr_pid.attr_name='_pid'
LEFT JOIN performance_schema.session_connect_attrs AS conattr_progname
ON conattr_progname.processlist_id=pps.processlist_id and conattr_progname.attr_name='program_name'
ORDER BY pps.processlist_time DESC, last_wait_latency DESC;
# 带x$前缀的视图查询语句与不带x$前缀的视图查询语句相比,只是少了单位格式化函数
......
下面我们看看使用该视图查询返回的结果
# 不带x$前缀的视图
admin@localhost : sys 04:27:20> select * from processlist where program_name='mysql' and trx_state is not null limit 1\G
*************************** 1. row ***************************
thd_id: 49
conn_id: 7
user: admin@localhost
db: sbtest
command: Sleep
state: NULL
time: 89
current_statement: NULL
statement_latency: NULL
progress: NULL
lock_latency: 157.00 us
rows_examined: 1000
rows_sent: 1000
rows_affected: 0
tmp_tables: 0
tmp_disk_tables: 0
full_scan: YES
last_statement: select * from sbtest1 limit 1000
last_statement_latency: 2.06 ms
current_memory: 0 bytes
last_wait: idle
last_wait_latency: Still Waiting
source: socket_connection.cc:69
trx_latency: 1.49 ms
trx_state: COMMITTED
trx_autocommit: YES
pid: 3927
program_name: mysql
1 row in set (0.13 sec)
# 带x$前缀的视图
admin@localhost : sys 04:27:28> select * from x$processlist where program_name='mysql' and trx_state is not null limit 1\G;
*************************** 1. row ***************************
thd_id: 49
conn_id: 7
user: admin@localhost
db: sbtest
command: Sleep
state: NULL
time: 150
current_statement: NULL
statement_latency: NULL
progress: NULL
lock_latency: 157000000
rows_examined: 1000
rows_sent: 1000
rows_affected: 0
tmp_tables: 0
tmp_disk_tables: 0
full_scan: YES
last_statement: select * from sbtest1 limit 1000
last_statement_latency: 2055762000
current_memory: 0
last_wait: idle
last_wait_latency: Still Waiting
source: socket_connection.cc:69
trx_latency: 1490662000
trx_state: COMMITTED
trx_autocommit: YES
pid: 3927
program_name: mysql
1 row in set (0.14 sec)
视图字段含义如下:
查看当前用户会话的进程列表信息,与processlist&x$processlist视图类似,但是session视图过滤掉了后台线程,只显示前台(用户)线程相关的统计数据,数据来源:sys.processlist
视图查询语句
# 不带x$的视图查询语句
## 只需要在processlist视图的查询语句上加上如下条件即可
......
[WHERE] conn_id IS NOT NULL AND command != 'Daemon';
# 带x$前缀的视图查询语句与不带x$前缀的视图查询语句相比,只是少了单位格式化函数
......
下面我们看看使用该视图查询返回的结果
# 不带x$前缀的视图
admin@localhost : sys 12:44:22> select * from session where command='query' and conn_id!=connection_id()\G
*************************** 1. row ***************************
thd_id: 48
conn_id: 6
user: admin@localhost
db: xiaoboluo
command: Query
state: Sending data
time: 72
current_statement: select * from test limit 1 for update
statement_latency: 1.20 m
progress: NULL
lock_latency: 169.00 us
rows_examined: 0
rows_sent: 0
rows_affected: 0
tmp_tables: 0
tmp_disk_tables: 0
full_scan: NO
last_statement: NULL
last_statement_latency: NULL
current_memory: 461 bytes
last_wait: wait/io/table/sql/handler
last_wait_latency: Still Waiting
source: handler.cc:3185
trx_latency: NULL
trx_state: NULL
trx_autocommit: NULL
pid: 3788
program_name: mysql
1 row in set (0.15 sec)
# 带x$前缀的视图
admin@localhost : sys 12:45:09> select * from x$session where command='query' and conn_id!=connection_id()\G;
*************************** 1. row ***************************
thd_id: 48
conn_id: 6
user: admin@localhost
db: xiaoboluo
command: Query
state: Sending data
time: 91
current_statement: select * from test limit 1 for update
statement_latency: 91077336919000
progress: NULL
lock_latency: 169000000
rows_examined: 0
rows_sent: 0
rows_affected: 0
tmp_tables: 0
tmp_disk_tables: 0
full_scan: NO
last_statement: NULL
last_statement_latency: NULL
current_memory: 461
last_wait: wait/io/table/sql/handler
last_wait_latency: Still Waiting
source: handler.cc:3185
trx_latency: NULL
trx_state: NULL
trx_autocommit: NULL
pid: 3788
program_name: mysql
1 row in set (0.13 sec)
视图字段含义
查看当前链接线程的MDL锁等待信息,显示哪些会话被MDL锁阻塞,是谁阻塞了这些会话,数据来源:performance_schema下的threads、metadata_locks、events_statements_current表
* 启用MDL锁的instruments:update setup_instruments set enabled='yes',timed='yes' where name='wait/lock/metadata/sql/mdl';
* 或者也可以使用sys 系统库下的辅助性视图操作:call sys.ps_setup_enable_instrument('wait/lock/metadata/sql/mdl');
视图定义语句文本
# 不带x$的视图查询语句
SELECT g.object_schema AS object_schema,
g.object_name AS object_name,
pt.thread_id AS waiting_thread_id,
pt.processlist_id AS waiting_pid,
sys.ps_thread_account(p.owner_thread_id) AS waiting_account,
p.lock_type AS waiting_lock_type,
p.lock_duration AS waiting_lock_duration,
sys.format_statement(pt.processlist_info) AS waiting_query,
pt.processlist_time AS waiting_query_secs,
ps.rows_affected AS waiting_query_rows_affected,
ps.rows_examined AS waiting_query_rows_examined,
gt.thread_id AS blocking_thread_id,
gt.processlist_id AS blocking_pid,
sys.ps_thread_account(g.owner_thread_id) AS blocking_account,
g.lock_type AS blocking_lock_type,
g.lock_duration AS blocking_lock_duration,
CONCAT('KILL QUERY ', gt.processlist_id) AS sql_kill_blocking_query,
CONCAT('KILL ', gt.processlist_id) AS sql_kill_blocking_connection
FROM performance_schema.metadata_locks g
INNER JOIN performance_schema.metadata_locks p
ON g.object_type = p.object_type
AND g.object_schema = p.object_schema
AND g.object_name = p.object_name
AND g.lock_status = 'GRANTED'
AND p.lock_status = 'PENDING'
INNER JOIN performance_schema.threads gt ON g.owner_thread_id = gt.thread_id
INNER JOIN performance_schema.threads pt ON p.owner_thread_id = pt.thread_id
LEFT JOIN performance_schema.events_statements_current gs ON g.owner_thread_id = gs.thread_id
LEFT JOIN performance_schema.events_statements_current ps ON p.owner_thread_id = ps.thread_id
WHERE g.object_type = 'TABLE';
# 带x$前缀的视图查询语句与不带x$前缀的视图查询语句相比,只是少了单位格式化函数
......
下面我们看看使用该视图查询返回的结果
admin@localhost : sys 11:31:57> select * from schema_table_lock_waits\G;
*************************** 1. row ***************************
object_schema: xiaoboluo
object_name: test
waiting_thread_id: 1217
waiting_pid: 1175
waiting_account: admin@localhost
waiting_lock_type: EXCLUSIVE
waiting_lock_duration: TRANSACTION
waiting_query: alter table test add index i_k(test)
waiting_query_secs: 58
waiting_query_rows_affected: 0
waiting_query_rows_examined: 0
blocking_thread_id: 49
blocking_pid: 7
blocking_account: admin@localhost
blocking_lock_type: SHARED_WRITE
blocking_lock_duration: TRANSACTION
sql_kill_blocking_query: KILL QUERY 7
sql_kill_blocking_connection: KILL 7
*************************** 2. row ***************************
object_schema: xiaoboluo
object_name: test
waiting_thread_id: 1217
waiting_pid: 1175
waiting_account: admin@localhost
waiting_lock_type: EXCLUSIVE
waiting_lock_duration: TRANSACTION
waiting_query: alter table test add index i_k(test)
waiting_query_secs: 58
waiting_query_rows_affected: 0
waiting_query_rows_examined: 0
blocking_thread_id: 1217
blocking_pid: 1175
blocking_account: admin@localhost
blocking_lock_type: SHARED_UPGRADABLE
blocking_lock_duration: TRANSACTION
sql_kill_blocking_query: KILL QUERY 1175
sql_kill_blocking_connection: KILL 1175
2 rows in set (0.00 sec)
视图字段含义如下:
本期内容就介绍到这里,本期内容参考链接如下:
https://dev.mysql.com/doc/refman/5.7/en/sys-schema-table-lock-waits.html
https://dev.mysql.com/doc/refman/5.7/en/sys-innodb-lock-waits.html
https://dev.mysql.com/doc/refman/5.7/en/sys-processlist.html
https://dev.mysql.com/doc/refman/5.7/en/sys-session.html
罗小波·沃趣科技高级数据库技术专家
IT从业多年,历任运维工程师,高级运维工程师,运维经理,数据库工程师,曾参与版本发布系统,轻量级监控系统,运维管理平台,数据库管理平台的设计与编写,熟悉MySQL的体系结构时,InnoDB存储引擎,喜好专研开源技术,追求完美。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。