IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 数据库锁表解决办法 -> 正文阅读

[大数据]数据库锁表解决办法

锁表产生场景以及原因

场景:

锁表通常发生在 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. 新建扩展表,但如果字段使用频繁会影响性能。

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

来源:https://zhuanlan.zhihu.com/p/437702115

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:46:25  更:2022-05-09 12:50:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:32:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码