全局锁 Global Read lock
a. 介绍
全局读锁。
加锁方法: FTWRL,flush tables with read lock. (flush tables:把当前系统当中已经打开的表关掉)
表关掉之后,加上锁,阻塞所有事务的提交commit
解锁方法: unlock tables;
FTWRL出现场景:
mysqldump --master-data
xtrabackup(8.0之前早期版本)等备份时。
8.0之后:
属于类型: MDL(matedatalock)层面锁
影响情况: 加锁期间,阻塞所有事务写入,阻塞所有已有事务commit。
MDL,等待时间受 lock_wait_timeout=31536000
场景: 业务反馈所有写入做不了.查询的相关
mysql> show processlist;
mysql> select * from performance_schema.metadata_locks\G
mysql> select * from sys.schema_table_lock_waits;
一个经典故障:5.7 xtrabackup/mysqldump备份时数据库出现hang状态,所有修改查询都不能进行
session1: 模拟一个大的查询或事务
mysql> select id,sleep(100) from city where id<100 for update ;
session2: 模拟备份时的FTWRL
mysql> flush tables with read lock;
-- 此时发现命令被阻塞
session3: 发起查询,发现被阻塞
mysql> select * from world.city where id=500 for update;
解决问题的步骤:
1.查看进程的详细信息
show processlist;
2.查看MDL锁信息
select * from performance_schema.metadata_locks\G
查看 PENDING 被阻塞 GRANTED 阻塞者的owner_therad_ID号
penging: 61 63 64
GRANTED: 62
3.# 通过SQL线程号找到 SQL语句,分析语句是谁堵塞了谁
select * from performance_schema.events_statements_history;(历史上运行的)
select * from performance_schema.events_statements_current;(正在运行的)
PENDING:
61:SQL_TEXT: flush tables with read lock
63:SQL_TEXT: select * from world.city where id=1 for update
64:SQL_TEXT: insert into student values(1,'asan')
GRANTED:
62:SQL_TEXT: select id,sleep(100) from city where id<100 for update(模拟执行了个大事务)
4.查看源头GRANTED:62能不能停(通过therad_ID找到processlist_Id) 找到是哪个用户或人员相连接做的操作,对相关人员询问
mysql>select * from performance_schema.threads where thread_id=62\G
THREAD_ID: 62
NAME: thread/sql/one_connection
TYPE: FOREGROUND
PROCESSLIST_ID: 22
PROCESSLIST_USER: root
PROCESSLIST_HOST: localhost
PROCESSLIST_DB: world
PROCESSLIST_COMMAND: Query
PROCESSLIST_TIME: 2130
PROCESSLIST_STATE: User sleep
PROCESSLIST_INFO: select id,sleep(100) from city where id<100 for update
PARENT_THREAD_ID: NULL
ROLE: NULL
INSTRUMENTED: YES
HISTORY: YES
CONNECTION_TYPE: Socket
THREAD_OS_ID: 3098
RESOURCE_GROUP: USR_default
1 row in set (0.00 sec)
5.如果要立即解决问题,让项目跑起来,通过找到备份(THREAD_ID为61)的连接线程PROCESSLIST_ID为21
mysql> select * from performance_schema.threads where thread_id=61\G
*************************** 1. row ***************************
THREAD_ID: 61
NAME: thread/sql/one_connection
TYPE: FOREGROUND
PROCESSLIST_ID: 21
PROCESSLIST_USER: root
PROCESSLIST_HOST: localhost
PROCESSLIST_DB: NULL
PROCESSLIST_COMMAND: Query
PROCESSLIST_TIME: 2581
PROCESSLIST_STATE: Waiting for global read lock
PROCESSLIST_INFO: flush tables with read lock
PARENT_THREAD_ID: 1
ROLE: NULL
INSTRUMENTED: YES
HISTORY: YES
CONNECTION_TYPE: Socket
THREAD_OS_ID: 6362
RESOURCE_GROUP: USR_default
1 row in set (0.00 sec)
6.杀掉进程21
结论: 备份时,一定要选择业务不繁忙期间,否则有可能会阻塞正常业务。
案例2:
5.7版本 innobackupex备份全库,进程死了,mysql里就是全库读锁,后边insert 全阻塞了
解决步骤和案例1类似