前言

前几天上午在对数据库的一张表进行操作的时候,由于这张表是按照时间的一张统计表,正好到那天没有测试数据了,于是我想将表中所有的时间,统一更新到后一个月,于是对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;

oracle大数据量更新引发的死锁问题解决方法及oracle分区和存储过程的思考的更多相关文章

  1. Oracle大数据量查询实际分析

    Oracle数据库: 刚做一张5000万条数据的数据抽取,当前表同时还在继续insert操作,每分钟几百条数据. 该表按照时间,以月份为单位做的表分区,没有任何索引,当前共有14个字段,平均每个字段3 ...

  2. mongo 大数据量更新注意事项

    1.大数据量最好在本地执行更新. 2.在客户端执行更新时需要注意serve活动时间(10分钟),10分钟内解决不了的使用batchSize  或者db.getCollection("&quo ...

  3. 大数据量场景下storm自定义分组与Hbase预分区完美结合大幅度节省内存空间

    前言:在系统中向hbase中插入数据时,常常通过设置region的预分区来防止大数据量插入的热点问题,提高数据插入的效率,同时可以减少当数据猛增时由于Region split带来的资源消耗.大量的预分 ...

  4. 大数据量高并发访问SQL优化方法

    保证在实现功能的基础上,尽量减少对数据库的访问次数:通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担:能够分开的操作尽量分开处理,提高每次的响应速度:在数据窗口使用SQL时,尽量把 ...

  5. mongo大数据量更新服务端超时解决: Cursor not found, cursor id: 82792803897

    mongodb pymongo.errors.CursorNotFound: Cursor not found, cursor id: 82792803897 默认 mongo server维护连接的 ...

  6. 浅谈PageHelper插件分页实现原理及大数据量下SQL查询效率问题解决

    前因:项目一直使用的是PageHelper实现分页功能,项目前期数据量较少一直没有什么问题.随着业务扩增,数据库扩增PageHelper出现了明显的性能问题.几十万甚至上百万的单表数据查询性能缓慢,需 ...

  7. oracle大数据量。表分区提示查询效率

    现在业务有一张usertrack 日志记录表.每天会产生30万条数据.数据量大查询效率会非常慢 所以我考虑通过表分区来提示效率  逻辑上是一张表.但是分区后会按照分区条件将数据分在不同的物理文件 优点 ...

  8. mysql大数据量下修改表结构的方法

    http://www.blogjava.net/anchor110/articles/361152.html

  9. Win环境下Oracle小数据量数据库的物理备份

    Win环境下Oracle小数据量数据库的物理备份 环境:Windows + Oracle 单实例 数据量:小于20G 重点:需要规划好备份的路径,建议备份文件和数据库文件分别存在不同的存储上. 1.开 ...

随机推荐

  1. leetcode — plus-one

    import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Source : https://o ...

  2. 【整理】WDK 和 DDK异同

    WDK和DDK的作用 开发WINDOWS下的驱动程序,需要一个专门的开发包,如:开发JAVA程序,我们可能需要一个JDK,开发 WINDOWS应用程序,我们需要WINDOWS的SDK,现在开发WIND ...

  3. python 闯关之路四(下)(并发编程与数据库编程)

    并发编程重点: 并发编程:线程.进程.队列.IO多路模型 操作系统工作原理介绍.线程.进程演化史.特点.区别.互斥锁.信号. 事件.join.GIL.进程间通信.管道.队列. 生产者消息者模型.异步模 ...

  4. 【mac】ansible安装及基础使用

    安装 环境释放 mac 10.12.5 #more /System/Library/CoreServices/SystemVersion.plist 安装命令 #ruby -e "$(cur ...

  5. [React] react.js的一些库和用法

    React性能优化 记录一次利用 Timeline/Performance工具进行 React性能优化的真实案例 http://www.jianshu.com/p/9b0e9ef0a607 React ...

  6. 我的python渗透测试工具之主机嗅探

    嗅探工具的主要目标是基于UDP发现目标网络中的存活主机,选择UDP的原因是UDP访问过程开销小. 由于很多的操作系统在处理UDP端口的闭合时都会存在一个共性,我们也正是利用这个共性来开展确定此IP上是 ...

  7. phpmyadmin创建mysql的存储过程

    通过phpmyadmin ,创建procedure, 用于生成测试数据. 随机的用户名及手机号. DELIMITER $$ CREATE PROCEDURE `sp_insert_test_users ...

  8. 【转载】C#常用数据库Sqlserver通过SQL语句查询数据库以及表的大小

    在Sqlserver数据库中,一般我们查看数据库的大小可以通过查找到数据库文件来查看,但如果要查找数据表Table的大小的话,则不可通过此方法,在Sqlserver数据库中,提供了相应的SQL语句来查 ...

  9. element-ui el-input只显示下划线

    只需要增加样式 .el-input__inner { width: 220px; border-top-width: 0px; border-left-width: 0px; border-right ...

  10. Android Studio添加Activity时Resolved versions for app (21.0.3) and test app (25.4.0) differ.

    将以下代码添加到gradle(module) dependencise中 androidTestCompile 'com.android.support:support-annotations:xx. ...