MYSQL 8 从metadata开始到如何获得语句由于获取锁失败的错误

本文探讨了MySQL中的元数据锁(metadatalock)及其在管理数据一致性中的作用,涉及创建删除索引、修改表结构等操作时的锁机制。通过查询信息_schema表可以发现长时间等待的事务,并通过特定SQL语句进行kill操作。此外,还提到了MySQL8.0后的prepare事务处理及错误日志在performance_schema中的记录,帮助用户监控和排查错误。

3392b86ed38349494f9ed6c812568154.png

最近有同学提出,你的文字还OK,就是排版有问题,嗯,的确。我的排版的确是很烂,我也想改变,可能基于工作中的时间问题,以及学习的速度,让我实在是没有能力在排版上下功夫。希望哪位好心的同学,可以给我一个方法来提高排版,并且不要花太多的心思在这里面,谢谢。

接着上期,metadata lock 到底是一个什么东西,首先metadata lock 是MYSQL 来管理一致性访问以及确认数据一致性所做得一个工作。metadata lock不光是应用于表的层面,同时也应用于schema, triiger,scheduled,function等层面。

Metadata锁的意义在于MYSQL 不会随便让数据写入到metadata 中,他要做的是维护数据在表中的一致性,举例当有表的操作在修改 metadata 中的数据的情况下,未提交的事务,或者是回滚的事务都需要等待metadata lock中的锁释放后,才能进行后续的工作。

那么接下来的问题是,metadata lock的锁会在什么时候在MYSQL 中工作的问题,

1  创建或删除索引

2  修改表结构

3  在对表进行optimize table , repair table ,delete table , table lock 生效时,这些都触发了metadata lock

select concat('kill ',i.trx_mysql_thread_id,';') 

from information_schema.innodb_trx i,   

(select  id, time      

from  information_schema.processlist      

where    time = (select  max(time)             

 from   information_schema.processlist              

where  state = 'Waiting for table metadata lock'                      

and substring(info, 1, 5) in ('alter' , 'optim', 'repai', 'lock ', 'drop ', 'creat'))) p   

where timestampdiff(second, i.trx_started, now()) > p.time   and i.trx_mysql_thread_id  not in (connection_id(),p.id);

通过这个方式可以将长时间等待metadata lock 不工作的事务从数据库中找出来, 并产生一个kill 的语句。

那么下面有一个问题,如果对一个表的锁定的解锁顺序是如何的,当我们针对一个表进行了 X锁的加持,后面我们先进行了一个插入的操作,然后在进行对表的rename的操作, 此时真正的顺序应该是

1   X 锁定标

2   INSERT 

3   RENAME

————————

1  解除X锁

2  RENAME 

3  INSERT 

另外在MYSQL 8.013后MYSQL prepare 事务的问题,在客户端和数据库失联的情况下,用户的prepare状态会被保持直到XA_COMMIT 或者 XA_ROLLBACK

除了这个问题以外,就是关于如何发现曾经MYSQL 发生过错误,一般的情况MYSQL 5.X我们都是去找到ERROR LOG ,里面去找寻可能发生的信息,但是MYSQL 8 我们在performance_schema 中已经有了 events_errors 系列,这些表可以让你从各个层面来了解MYSQL 在最近都发生过什么错误。

1  event_error_summary_global_by_error

通过这个表,我们查看这个表可以记录的错误的种类有 5017种

select count(distinct error_name) from performance_schema.events_errors_summary_global_by_error;

3fac3f8a58213a9041d94b51f156376a.png

select * from performance_schema.events_errors_summary_global_by_error where error_name IN  ('ER_LOCK_WAIT_TIMEOUT','ER_LOCK_DEADLOCK','ER_LOCK_TABLE_FULL')\G

ac57bb2ef16e2e5dd78bef2e387e44de.png

在这个表里面分别有三个记录与我们日常所有关的方向,

'ER_LOCK_WAIT_TIMEOUT',   发生过程序block的情况

'ER_LOCK_DEADLOCK',          发生过程序死锁的情况

'ER_LOCK_TABLE_FULL'          发生过全表扫描的情况

select * from events_errors_summary_by_user_by_error where last_seen is not null;    以上的这个表,主要是从访问数据库的用户的角度来出发,查看这个用户曾经发生过什么样的错误,我们可以改写一下这个查询的语句,来更精确的对这个账号发生过什么错误进行判断。

00ef3abe3e0f7ef9e6bbc4e92a862b3b.png

select USER,ERROR_NAME,last_seen,sum_error_raised from events_errors_summary_by_user_by_error where SUM_ERROR_RAISED > 0 and error_name in ('ER_LOCK_WAIT_TIMEOUT','ER_LOCK_DEADLOCK','ER_LOCK_TABLE_FULL');

dc91974bec9024a99ae84c3313a374b9.png


上面的语句可以发现你最后一次产生查询问题的账号以及问题的原因,和发生的次数的递增,这里可以做定期的信息收集,然后对比同一个时期的信息差,来发现更多的问题。

30b40c7fe5ec64157b819b0928ab2fe8.png

### MySQL语句的类型 在MySQL中,语句主要用于管理表级,确保数据的一致性和完整性。语句的类型主要包括以下几种: #### 1. `LOCK TABLES` 和 `UNLOCK TABLES` `LOCK TABLES` 是一种显式的表命令,用于手动定一个或多个表。它可以指定不同的模式,包括读(`READ`)和写(`WRITE`)。例如: ```sql LOCK TABLES table_name READ; LOCK TABLES table_name WRITE; ``` - **读**:允许多个会话同时读取表中的数据,但不允许任何会话修改数据[^3]。 - **写**:独占表,只有持有写的会话可以对表进行读写操作,其他会话必须等待释放[^3]。 当完成操作后,需要通过 `UNLOCK TABLES` 显式地释放: ```sql UNLOCK TABLES; ``` #### 2. 隐式 隐式是由存储引擎自动管理的,通常与事务相关。InnoDB 存储引擎使用行级,而 BDB 存储引擎使用页级。当执行某些 SQL 操作时,存储引擎会根据需要自动捕获[^5]。例如: - 在插入、更新或删除数据时,InnoDB 会自动捕获行级- 如果事务涉及大量数据更新或全表扫描,MySQL 可能会将行升级为表,以减少冲突和死的可能性[^2]。 #### 3. 元数据Metadata Lock, MDL) 元数据MySQL 自动施加的一种,用于确保 DDL 和 DML 操作之间的兼容性。当执行查询、更新或其他操作时,MySQL 会自动为相关表施加元数据。如果某个事务长时间持有元数据,可能会导致其他会话的查询或 DDL 操作被阻塞[^4]。 #### 4. 死检测与超时 在多事务并发的情况下,可能会发生死。InnoDB 存储引擎会自动检测死,并选择一个事务进行回滚以解除死。此外,MySQL 提供了 `innodb_lock_wait_timeout` 参数,用于设置等待超时的时间。如果某个事务等待的时间超过了该参数值,则会报错并提示重新启动事务[^2]。 ### 示例代码 以下是一个简单的示例,展示如何使用 `LOCK TABLES` 和 `UNLOCK TABLES`: ```sql -- 定表以进行写操作 LOCK TABLES users WRITE; -- 执行写操作 UPDATE users SET status = 'active' WHERE id = 1; --表 UNLOCK TABLES; ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值