好友
阅读权限10
听众
最后登录1970-1-1
|
k168
发表于 2023-8-4 17:23
在职业生涯中,总会遇到数据库表被锁的情况,前些天就又撞见一次。由于业务突发需求,各个部门都在批量操作、导出数据,而数据库又未做读写分离,结果就是:数据库的某张表被锁了!
来看看不用跑路的解决方案:
遇到数据库阻塞问题,首先要查询一下表是否在使用.如果查询结果为空,那么说明表没在使用,说明不是锁表的问题如果查询结果不为空,比如出现如下结果:
则说明表 (test) 正在被使用,此时需要进一步排查查看数据库当前的进程,看看是否有慢SOL或被阻赛的线程.执行命令:
该命令只显示当前用户正在运行的线程,当然,如果是root用户是能看到所有的.
在上述实践中,阿里云控制台之所以能够查看到所有的线程,猜测应该使用的就是root用户,而笔者去kll的时候,无法kll掉,是因为登录的用户非root的数据库账号,无法操作另外一个用户的线程。
如果情况紧急,此步骤可以跳过,主要用来查看核对:
看事务表INNODB TRX中是否有正在锁定的事务线程,看看ID是否在show processlist的sleep线程中。如果在,说明这个sleep的线程事务一直没有commit或者rollback,而是卡住了,需要手动kill掉.搜索的结果中,如果在事务表发现了很多任务,最好都kill掉。执行kll命令:
对应的线程都执行完kill命令之后,后续事务便可正常处理.针对紧急情况,通常也会直接操作第一、第二、第六步这里再补充一些MySQL锁相关的知识点: 数据库锁设计的初衷是处理并发问题,作为多用户共享的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则,而锁就是用来实现这些访问规则的重要数据结构,根据加锁的范围,MySQL里面的锁大致可以分成全局锁、表级锁和行锁三类。MySQL中表级别的锁有两种: 一种是表锁,一种是元数据锁 (metadata lock,MDL)
表锁是在Server层实现的,ALTER TABLE之类的语句会使用表锁,忽略存情引擎的锁机制。表锁通过lock tables...! ead/write来实现,而对于lInnoDB来说,一般会采用行级锁。毕竟锁住整张表影响范围太大了。
另外一个表级锁是MDL (metadata lock) ,用于并发情况下维护数据的一致性,保证读写的正确性,不需要显式的使用,在访问一张表时会被自动加上常见的一种锁表场景就是有事务操作处于: Waiting for table metadata lock状态
MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.
旦alter table TableA的操作停滞在Waiting for table metadata lock状态,后续对该表的任何操作 (包括读)都无法进行,因为它们也会在Opening tables的阶段进入到Waiting for table metadata lock的锁等待队列,如果核心表出现了锁等待队列,就会造成灾难性的后果。
通过show processlist可以看到表上有正在进行的操作 (包括读),此时alter table语句无法获取到metadata 独占锁,会进行等待。
通过show processlist看不到表上有任何操作,但实际上存在有未提交的事务,可以在information schema.innodbtrx中查看到。在事务没有完成之前,表上的锁不会释放,alter table同样获取不到metadata的独占锁。
处理方法: 通过 select *from information schema,innodb trxG,找到未提交事物的sid,然后kll,让其回滚通过show processlist看不到表上有任何操作,在information schemainnodb trx中也没有任何进行中的事务,很可能是因为在一个显式的事务中,对表进行了一个失败的操作(比如查询了一个不存在的字段),这时事务没有开始,但是失败语句获取到的锁依然有效,没有释放,从performance schema.events statements current表中可以查到失败的语句
处理方法: 通过performance schemaevents statements current找到其sid,kill 该session,也可以kill掉DDL所在的session。
总之,alter table的语句是很危险的(核心是未提交事务或者长事务导致的),在操作之前要确认对要操作的表没有任何进行中的操作、没有未提交事务、也没有显式事务中的报错语句,如果有alter table的维护任务,在无人监管的时候运行,最好通过lock wait timeout设置好超时时间,避免长时间的metedata锁等待.
关于MvSQL的锁表其实还有很多其他场景,我们在实践的过程中尽量避免锁表情况的发生,当然这需要一定经验的支撑。但更重要的是,如果发现锁表我们要能够快速的响应,快速的解决问题,避免影响正常业务,避免情况进一步恶化。所以,本文中的解决思路大家一定要收藏或记忆一下,做到有备无患,避免突然状况下抓瞎.
Mysql锁表解锁方式:
查询是否锁表
show OPEN TABLES :
查询进程
show processlist :
-- 查询到相对应的进程,然后杀死进程
kill id;-- -般到这一步就解锁了
-- 查看正在锁的事务
SELECT*FROM INFORMATION SCHEMA.INNODB LOCKS:
-- 查看等待锁的事务
SELECT* FROM INFORMATION SCHEMAINNODB LOCK WAITS:
-- 解锁表
UNLOCK TABLES,
MySQL锁表和解锁操作
确定mysol有锁表的情况则使用以下命令查看锁表进程
杀掉查询结果中已经锁表的trx mysgl thread id
扩展:
1、查看锁的事务
2、查看等待锁的事务
3、查询是否锁表:
查询进程
MYSQL完美解决生产环境改表结构锁表问题
有时候,会很不小心,在业务运行中执行了一条锁表语句。这时候该怎么办?例如: 修改元数据
SHOW FULL PROCESSLIST 查看一下:
发现修改之后,锁表了。这时候怎么办? 杀死它 KILL 4623660然后一切又恢复正常了。
般对于数据量较大的表,需要修改表结构,或者做一些耗时比较久的锁表操作,建议在晚上(业务闲时)执行。这个时候可以配合使用任务处理一下。
如: 修改一个表的字段长度,和添加索引,添加唯一索引示例
MYSQL存储过程结合任务处理耗时操作
mysql锁表问题分析以及解决方法-简书
项目坑有千千万,我们静下心来还是可以找到解决办法的最近接了一个由供应商留下来的项目,正是周末休息时间突然一个电话说功能用不了,翻看日志发现是业务功能的表被锁了,我就奇了怪了,天天没事,突然周末来使儿。一番了解才发现那个锁表情况是天天都有的,但是一直没找到原因,所以DBA运维同事天天充当定时删除机器,每天是上清除锁表进程,丢失的数据也手动补录,厉害了,这就是供应商做的项目吗? 烂到这个层度 (叶槽一番回到正题,我们来聊一聊我的解决步骤
mysql表被锁了怎么解锁
重启mysql服务
执行show processlist,找到state,State状态为Locked即被其他查询锁住。KILL 10866 |
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|