数据库锁表?别慌,本文教你如何解决

2023-11-16

引言

作为开发人员,我们经常会和数据库打交道。

当我们对数据库进行修改操作的时候,例如添加字段,更新记录等,没有正确评估该表在这一时刻的使用频率,直接进行修改,致使修改操作长时间无法响应,造成锁表,在 mysql 中,如果出现 alter 操作引发Waiting for table metadata lock 类型的锁表,会导致任何操作不可用,后果是灾难性的。

程序设计不合理,频繁对同一张表进行修改操作,同样可能引发锁表。

数据库锁表问题一旦出现,往往都是很致命的,锁表时间过久,可能会造成大量请求阻塞异常,影响系统业务正常开展。本文将详细阐述数据库锁表原因,解锁以及如何避免锁表,希望能对你有所帮助。

锁表产生场景以及原因

场景:

锁表通常发生在 DML( insert 、update 、delete )语句中,例如: 程序A 对 A表 的 a数据 进行修改,修改过程中产生错误,没有commit也没有rollback,这个时候 程序B 对 A表 的 a数据库进行修改,会产生资源正忙的异常,也就是锁表。

DDL也会引发锁表,例如在 MySql 操作一张大表,利用 alter 语句修改或新增字段的时候,恰巧有一个长事务(包括读)在操作此表,会触发修改等待,造成锁表。

原因:

当多个事务处理对多个资源同时访问时,若双方已锁定一部分资源但也都需要对方已锁定的资源时,无法在有限的时间内完全获得所需的资源,就会处于无限的等待状态,从而造成其对资源需求的死锁,导致锁表。

如何解锁

锁表一旦产生,需要我们尽快对其解锁,释放资源,不然会一直阻塞,下面主要讲解 MySql 和 Oracle 数据库的解锁方式。

MySql 解锁:

执行sql:

select * from information_schema.processlist where command not in ('Sleep') ORDER BY time desc

通过此 sql 可以查询到以下内容:
得到内容
sql已经按照阻塞时长从大到小排序,找到耗时长的记录 id ,kill 即可:

kill 16519789

通过此命令也可以查询到 mysql 的慢sql 语句,进行优化,info字段即为具体执行的sql语句。

oracle解锁:

执行以下sql:

SELECT SESS.SID,  
SESS.SERIAL#,  
LO.ORACLE_USERNAME,  
LO.OS_USER_NAME,  
AO.OBJECT_NAME 被锁对象名, 
LO.LOCKED_MODE 锁模式, 
sess.LOGON_TIME 登录数据库时间,
'ALTER SYSTEM KILL SESSION ''' || SESS.SID || ','||SESS.SERIAL#||'''' FREESQL
FROM V$LOCKED_OBJECT LO,  DBA_OBJECTS AO,  V$SESSION SESS 
WHERE AO.OBJECT_ID = LO.OBJECT_ID 
AND LO.SESSION_ID = SESS.SID 
ORDER BY sid, sess.serial#;

通过此sql可以查询到以下内容:
得到内容
然后复制最后一列 FREESQL 的内容,直接执行即可。

复制完执行可能会报错:ORA-00031: session marked for kill,这表示ORACLE已经把它标记为一个杀死的进程,但暂时无法将其彻底杀死,这个时候需要我们执行下面的sql,查出它在服务器上的进程id:

# sid 为上面sql 查出来的 sid
select spid, osuser, s.program
   from v$session s,v$process p
   where s.paddr=p.addr
   and s.sid='24986' 

通过上方 sql 可以得到服务器上的进程 id,登录数据库所在服务器,利用 kill 命令将其杀死即可:

kill -9 12009(查出来的spid)

oracle查询指定时间内的慢sql:

select *
 from (select sa.SQL_TEXT,
        sa.SQL_FULLTEXT,
        sa.EXECUTIONS "执行次数",
        round(sa.ELAPSED_TIME / 1000000, 2) "总执行时间",
        round(sa.ELAPSED_TIME / 1000000 / sa.EXECUTIONS, 2) "平均执行时间",
        sa.COMMAND_TYPE,
        sa.PARSING_USER_ID "用户ID",
        u.username "用户名",
        sa.HASH_VALUE
     from v$sqlarea sa
     left join all_users u
      on sa.PARSING_USER_ID = u.user_id
     where sa.EXECUTIONS > 0 and sa.LAST_ACTIVE_TIME >to_date( '2021-11-18 00:00:00','yyyy-mm-dd hh24:mi:ss')
     order by (sa.ELAPSED_TIME / sa.EXECUTIONS) desc)
 where rownum <= 50;

根据查询到的慢 sql 结果可以对相关 sql 进行优化。

如何避免锁表

通常情况下,数据库锁表大多是因为程序设计不合理导致的,在写代码的时候,我们要对业务场景充分考虑,尽量做到以下两点:

  1. 尽量减少程序中的 DML(insert,update,delete) 操作所花费的时间,对此类操作做好隔离控制,防止阻塞。
  2. 如果事务产生异常,确保事务可以正常回滚。

此外,不要轻易对线上数据库进行 DDL 操作,尤其是使用量大且频繁的数据表,强行修改可能会引发灾难性后果,目前修改线上表结构主要有以下几种方式:

  1. 等到使用量小的时候(例如半夜)修改,但有一定风险
  2. 暂时停止服务,修改完毕再上线,但会影响用户体验
  3. 复制旧表结构到新表,旧表创建触发器,旧表操作同步执行到新表,然后对新表修改表结构,同步旧数据到新表,锁旧表(只读),最后新表替换旧表,此方案基本对用户体验无影响,但操作较为复杂。
  4. 扩展表,如果字段使用频繁会影响性能。

在实际生产中,我们需要根据具体场景去选择适合自己的表结构变更方式。

结语

本文就数据库锁表问题进行了较为详细的探讨,喜欢的朋友可以收藏下,以备不时之需。

在真实的生产环境中,一般都会专门部署一套用来监测数据库的应用,一旦发现锁表或慢sql会及时报警通知相关负责人处理,但查询锁表以及解锁的相关sql还是需要我们特别掌握一下,也许在关键时刻就会发挥作用。

关注公众号 螺旋编程极客 第一时间解锁精彩内容,同时可获取独家研发的 代码生成器,提升开发效率

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据库锁表?别慌,本文教你如何解决 的相关文章

随机推荐

  • 支持向量机算法(SVM)详细讲解(含手推公式)(《机器学习》--周志华)

    前言 本人是一个本科到研究生都坚持本专业的人 但是 本科时间被狗吃了 目前还是小白一只 曾经以为考研之后要继续学习一技之长找个工作养活自己 当然 现在发现这都是自己想太多了 哈哈哈 读研之后才知道基础不好的人学习起来是多么困难 但是 既然选
  • 深度学习实战:使用 PyTorch 和序列到序列(Seq2Seq)模型进行机器翻译

    机器翻译是自然语言处理中的一个重要任务 它涉及将一种语言的文本转换为另一种语言的文本 序列到序列 Seq2Seq 模型是一种强大的深度学习模型 用于处理机器翻译任务 在本篇博客中 我们将使用 PyTorch 和 Seq2Seq 模型进行机器
  • 我00后,会Python,月薪5000,兼职1.5w

    当代年轻人的终极烦恼 没钱 主业收入不高但处处都要花钱 特别是今年以来 很多人会在后台问我 做些什么副业好 兼职写文 不知道上哪儿找单 自己也不一定写得好 做wei商 被朋友屏蔽 没有客源也出不了单 摆地摊 东西卖不出去反而倒贴了一笔钱 淘
  • vue中实现点击展开和收起功能(具有动画效果)

    vue中实现点击展开和收起功能 具有动画效果 html div class marketplace aside b div class marketplace aside show that item text div div
  • 一个好玩的小游戏——麻神之战

    题目 一种新的麻将 只留下一种花色 并且除去了一些特殊和牌方式 例如七对子等 规则如下 共有36张牌 每张牌是1 9 每个数字4张牌 你手里有其中的14张牌 如果这14张牌满足如下条件 即算作和牌 14张牌中有2张相同数字的牌 称为雀头 除
  • Java 同步JSON字符串至ES(Elasticsearch) 添加时间戳(@timestamp)、版本(@version) 字段

    解决方法 仿照logstash同步原理 对于同步json字符串 首先将其解析 然后添加时间戳和版本字段 或其他字段 打入es public void insertEs String jsonStr JSONObject jsonObject
  • 95-36-210-ChannelHandler-系统Channel-TimeoutHandler

    文章目录 1 概述 2 继承体系 3 IdleStateHandler 3 1 典型构造方法 3 2 初始化方法 initialize 3 3 销毁方法destroy 3 4 核心的调度任务 ReaderIdleTimeoutTask 1
  • QT的补充知识

    一 文件 QFile QT提供了QFile类用于对文件进行读写操作 也提供了其他的两个类 文本流 QTextSream 和数据流 QDataStream 文本流 QTextSream 用于对文本数据的处理 并且是以字为单位进行读 写 数据流
  • 获取执行计划——使用动态性能视图和AWR、Statspacks

    上一篇中讲了如何使用EXPLAIN PLAN方法来获取sql执行计划 这篇继续讲另两种方法 使用动态性能视图和AWR报告 一 使用动态性能视图 查询动态性能视图我们可以获取丰富的信息 包括执行计划与游标信息等等 下面罗列几个常用的v 视图
  • Python IDLE 自动提示功能

    Python27 Lib idlelib 目录下 config extensions def文件修改等待时间 AutoComplete enable 1 popupwait 2000 2000表示2秒 修改为0 AutoComplete p
  • 分享一个页面

    先看效果 看下代码
  • 34. 注入篇——Cookie注入

    Cookie注入原理 1 数据读取流程 对于WEB服务器而言 读取数据的流程是先取GET中的数据 如果GET中没有数据信息 那么再取POST中的数据 如果POST中也没有那么就会去取COOKIE中的数据 2 防注入系统的常例 系统一般只会对
  • flutter两个非常常用的布局小空间SizedBox和Divider

    SizedBox SizedBox是Flutter中的一个小部件 widget 用于创建具有指定尺寸的空白框 它通常用于调整和控制布局中的间距 大小和位置 SizedBox具有以下常用属性 width 指定SizedBox的宽度 heigh
  • Redis 五大基础数据结构命令详细介绍

    文章目录 一 Redis数据结构 二 Redis通用命令 三 String类型 3 1 String类型 也就是字符串类型 是Redis中最简单的存储类型 3 2 String类型的常见命令 四 Redis key的层级格式 4 1 key
  • GPT发家史

    如今 ML 领域公号也卷得厉害 最早我 reddit 灌灌水 邮件看看 就有东西写了也不怕重 现在基本上能第一眼看到的东西肯定还没动手大号们就发完了 前段时间 DALL E 刚出 果然还没动手写 无数文章就给介绍完了 对个人而言 要写的话要
  • mysql之分页查询14

    1 分页查询 分页查询比较简单 主要是使用limit关键字去分页 一般理解分页公式limit page 1 size size 即可 进阶8 分页查询 应用场景 当要显示的数据 一页显示不全 需要分页提交sql请求 语法 select 查询
  • 【Git】Git切换地址

    如何切换git代码地址 1 查看当前远程 url git remote v 执行命令后 可以看见当前有2个URL 远程 URL 在一般情况下有两个 分别是 fetch 和 push fetch URL 是用于从远程仓库获取最新版本的数据 当
  • Java面向对象进阶&继承

    1 继承 1 1 继承的实现 继承的概念 继承是面向对象三大特征之一 可以使得子类具有父类的属性和方法 还可以在子类中重新定义 以及追加属性和方法 实现继承的格式 继承通过extends实现 格式 class 子类 extends 父类 举
  • 水仙花数(Java语言)——最基础全面的讲解

    题目 判读一个整数是否是水仙花数 所谓水仙花数是一个三位数 其各个位上数字立方和等于它本身 例如 153 1 1 1 3 3 3 5 5 5 首先进行思路分析 1 首先要得到此数百位 十位 个位上的数字 然后用 if 判断他们的立方和是否相
  • 数据库锁表?别慌,本文教你如何解决

    引言 作为开发人员 我们经常会和数据库打交道 当我们对数据库进行修改操作的时候 例如添加字段 更新记录等 没有正确评估该表在这一时刻的使用频率 直接进行修改 致使修改操作长时间无法响应 造成锁表 在 mysql 中 如果出现 alter 操