引言
作为开发人员,我们经常会和数据库打交道。
当我们对数据库进行修改操作的时候,例如添加字段,更新记录等,没有正确评估该表在这一时刻的使用频率,直接进行修改,致使修改操作长时间无法响应,造成锁表,在 mysql 中,如果出现 alter 操作引发Waiting for table metadata lock 类型的锁表,会导致任何操作不可用,后果是灾难性的。
程序设计不合理,频繁对同一张表进行修改操作,同样可能引发锁表。
数据库锁表问题一旦出现,往往都是很致命的,锁表时间过久,可能会造成大量请求阻塞异常,影响系统业务正常开展。本文将详细阐述数据库锁表原因,解锁以及如何避免锁表。
锁表产生场景以及原因
场景:
锁表通常发生在 DML( insert 、update 、delete )语句中,例如: 程序A 对 A表 的 a数据 进行修改,修改过程中产生错误,没有commit也没有rollback,这个时候 程序B 对 A表 的 a数据库进行修改,会产生资源正忙的异常,也就是锁表。
DDL也会引发锁表,例如在 MySql 操作一张大表,利用 alter 语句修改或新增字段的时候,恰巧有一个长事务(包括读)在操作此表,会触发修改等待,造成锁表。
原因:
当多个事务处理对多个资源同时访问时,若双方已锁定一部分资源但也都需要对方已锁定的资源时,无法在有限的时间内完全获得所需的资源,就会处于无限的等待状态,从而造成其对资源需求的死锁,导致锁表。
如何解锁
锁表一旦产生,需要我们尽快对其解锁,释放资源,不然会一直阻塞,下面主要讲解 MySql 数据库的解锁方式。
MySql 解锁:
执行sql:
select * from information_schema.processlist where command not in ('Sleep') ORDER BY time desc
通过此 sql 可以查询到以下内容:
sql已经按照阻塞时长从大到小排序,找到耗时长的记录 id ,kill 即可:
kill 16519789
如何避免锁表
通常情况下,数据库锁表大多是因为程序设计不合理导致的,在写代码的时候,我们要对业务场景充分考虑,尽量做到以下两点:
- 尽量减少程序中的 DML(insert,update,delete) 操作所花费的时间,对此类操作做好隔离控制,防止阻塞。
- 如果事务产生异常,确保事务可以正常回滚。