百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

oracle大数据量更新引发的死锁问题解决方法

sinye56 2024-09-29 22:10 6 浏览 0 评论

前言

前几天上午在对数据库的一张表进行操作的时候,由于这张表是按照时间的一张统计表,正好到那天没有测试数据了,于是我想将表中所有的时间,统一更新到后一个月,于是对80w条数据的更新开始了。整个过程曲折的一批。同时学到了很多知识,在此进行记录。希望对大家有帮助。

首先是大批量更新,由于数据已经进行了分区,开始对分区进行分析,然后大批量操作死锁,对死锁的解决,最后存储过程来解决数据的大批量插入。

曲折的过程开始

由于测试数据到21号就没了,21号一上去,发现开发的功能,都没有数据了,图表也都空了。查询原因发现测试数据没了。于是打算开始造数据。此时数据库已经有80多w的数据,当时想着将所有数据的collect_time时间字段向后推迟一个月,即可。当时也没想优化问题。于是写下sql。

update i_people_collect set collect_time = collect_time+30
复制代码

此sql将表的所有时间向后推迟一个月。于是开始执行。

此时报错:ORA-14402: 更新分区关键字列将导致分区的更改。

于是发现此表的collect_time列进行了分区处理。

我们可以先开启表的行移动来允许对分区字段的update 操作。sql如下

alter table xxx enable row movement;
复制代码

之后再执行update发现可以执行,执行完毕后,记得关闭行移动。

alter table xxx disable row movement;
复制代码

回到刚才我们执行update语句,预计会慢,但是发现执行了20分钟还没有结束。于是怀疑报错了。就强行终止。但是此时终止也不好使了。。大概是占用资源太多,不好释放。

于是强行关掉pl/sql。重新登录。这里我们先分析一下,执行update操作为什么会这么慢。

分区表某一行更新时,如果更新的是分区列,并且更新后的列值不属于原来的这个分区,如果开启了这个选项,就会把这行从这个分区中delete掉,并加到更 新后所属的分区。相当于一个隐式的delete+insert,但是不会触发insert/delete触发器。如果没有开启这个选项,就会在更新时报错 ORA-14402;

这一操作产生影响的特殊之处在于这是个DML操作,是和online transaction密切相关。对于这样一个UPDATE,实际上分为3步:先从原有分区将数据删除;将原数据转移到新分区上;更新数据。

其影响就在于以下几个方面:

一 个UPDATE被分解为DELET、INSERT、UPDATE三个操作,增加了性能负担。其中,DELETE的查询条件与原UPDATE的查询条件相 同,新的UPDATE的查询条件是基于INSERT生成的新的ROWID,相应的Redo Log、Undo Log会增加;

如果Update语句还涉及到了Local Index的字段的话,新、旧2个分区上的Local Index都要被更新。

由于我们更新的是collect_time列。collect_time列又正好是分区列。于是就产生了上面的这种情况。造成执行速度十分的缓慢。

原因分析完毕。继续说接下来发生的问题。

重新连接到PL/Sql后,对刚才的表进行查询,发现一直执行sql,并不返回结果。于是考虑刚才的sql还在执行的问题。

通过pl/sql的工具,会话,发现刚才的会话仍然存在,没有断开连接。这就坑爹了啊。通过会话来对连接强制结束。发现还是不能操作刚才的表。于是考虑了一下,可能是表发生了死锁。

于是执行查询哪些表产生了死锁的sql,如下

select b.owner,b.object_name,a.session_id,a.locked_mode from v$locked_object a,dba_objects b where b.object_id = a.object_id;
复制代码

通过结果发现,刚才的表果然已经被锁定了。

继续向下看是哪个用户的哪个进程造成的死锁

--查看那个用户那个进程照成死锁
select b.username,b.sid,b.serial#,logon_time from v$locked_object a,v$session b where a.session_id = b.sid order by b.logon_time;
复制代码
--查看连接的进程 
SELECT sid, serial#, username, osuser FROM v$session;
复制代码
--查出锁定表的sid, serial#,os_user_name, machine_name, terminal,锁的type,mode
SELECT s.sid, s.serial#, s.username, s.schemaname, s.osuser, s.process, s.machine,
s.terminal, s.logon_time, l.type
FROM v$session s, v$lock l
WHERE s.sid = l.sid
AND s.username IS NOT NULL
ORDER BY sid;
复制代码

此时通过这些查询,我们已经能够定位是哪个进程导致了锁表的产生。同时获取到了进程的sid以及serial。

执行中断进程的sql,

alter system kill session'210,11562';
复制代码

讲道理,此时已经进行了进程的结束,但是发现表还是在锁着的。于是可能是查看一下造成死锁的这一进程的状态。

select saddr, sid, serial#, paddr, username, status, machine from v$session where username is not null
复制代码

通过status发现锁定的进程的状态已经改变为KILLED,这种状态可能导致长时间的未释放资源,PMON并没有对其进行清除,等了很久仍然是锁表状态。

于是可能需要操作系统级别的对进程进行清除。

我们查询出会话进程在操作系统中的进程id。

select a.spid,b.sid,b.serial#,b.username,b.status from v$process a,v$session b where a.addr=b.paddr ; 
复制代码

我们进入linux后台。通过kill -9 spid,此时执行后,发现表已经解锁了,死锁结束。呼~不容易。

接下来问题又来了,我们如何继续更新数据呢。最终决定实用存储过程来进行增加数据。

create or replace procedure aaa(startdate in date, days in number) as
--生成的数据包含startdate当天
i number;
begin
  i := 0;
  while i < days loop
      insert into aaa1
      select sec_pkid.nextval,startdate + i,
      '字段名','字段名','字段名','字段名'
      from aaa2 t where collect_time = to_date('2018-11-09','yyyy-mm-dd');
      i := i+1;
      commit;
  end loop;
end aaa;


作者:经典鸡翅
链接:https://juejin.cn/post/7025982805460926478
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关推荐

RHEL8和CentOS8怎么重启网络

本文主要讲解如何重启RHEL8或者CentOS8网络以及如何解决RHEL8和CentOS8系统的网络管理服务报错,当我们安装好RHEL8或者CentOS8,重启启动网络时,会出现以下报错:...

Linux 内、外网双网卡路由配置

1.路由信息的影响Linux系统中如果有多张网卡的情况下,如果路由信息配置不正确,...

Linux——centos7修改网卡名

修改网卡名这个操作可能平时用不太上,可作为了解。修改网卡默认名从ens33改成eth01.首先修改网卡配置文件名(建议将原配置文件进行备份)...

CentOS7下修改网卡名称为ethX的操作方法

?Linux操作系统的网卡设备的传统命名方式是eth0、eth1、eth2等,而CentOS7提供了不同的命名规则,默认是基于固件、拓扑、位置信息来分配。这样做的优点是命名全自动的、可预知的...

Linux 网卡名称enss33修改为eth0

一、CentOS修改/etc/sysconfig/grub文件(修改前先备份)为GRUB_CMDLINE_LINUX变量增加2个参数(net.ifnames=0biosdevname=0),修改完成...

CentOS下双网卡绑定,实现带宽飞速

方式一1.新建/etc/sysconfig/network-scripts/ifcfg-bond0文件DEVICE=bond0IPADDR=191.3.60.1NETMASK=255.255.2...

linux 双网卡双网段设置路由转发

背景网络情况linux双网卡:网卡A(ens3)和网卡B(...

Linux-VMware设置网卡保持激活

Linux系统只有在激活网卡的状态下才能去连接网络,进行网络通讯。修改配置文件(永久激活网卡)...

VMware虚拟机三种网络模式

01.VMware虚拟机三种网络模式由于linux目前很热门,越来越多的人在学习linux,但是买一台服务放家里来学习,实在是很浪费。那么如何解决这个问题?虚拟机软件是很好的选择,常用的虚拟机软件有v...

Rocky Linux 9/CentOS Stream 9修改网卡配置/自动修改主机名(实操)

推荐...

2023年最新版 linux克隆虚拟机 解决网卡uuid重复问题

问题描述1、克隆了虚拟机,两台虚拟机里面的ip以及网卡的uuid都是一样的2、ip好改,但是uuid如何改呢?解决问题1、每台主机应该保证网卡的UUID是唯一的,避免后面网络通信有问题...

Linux网卡的Vlan配置,你可能不了解的玩法

如果服务器上连的交换机端口已经预先设置了TRUNK,并允许特定的VLAN可以通过,那么服务器的网卡在配置时就必须指定所属的VLAN,否则就不通了,这种情形在虚拟化部署时较常见。例如在一个办公环境中,办...

Centos7 网卡绑定

1、切换到指定目录#备份网卡数据cd/etc/sysconfig/network-scriptscpifcfg-enp5s0f0ifcfg-enp5s0f0.bak...

Linux搭建nginx+keepalived 高可用(主备+双主模式)

一:keepalived简介反向代理及负载均衡参考:...

Linux下Route 路由指令使用详解

linuxroute命令用于显示和操作IP路由表。要实现两个不同子网之间的通信,需要一台连接两个网络的路由器,或者同时位于两个网络的网关来实现。在Linux系统中,设置路由通常是为了解决以下问题:该...

取消回复欢迎 发表评论: