我们要看到Oracle Update的另一个方面,就是Undo、Redo和进程工作负载的问题。熟悉Oracle的朋友们知道,在DML操作的时候,Undo和

SQL语句是一种方便的语言,同样也是一种“迷惑性”的语言。这个主要体现在它的集合操作特性上。无论数据表数据量是1条,还是1亿条,更新的语句都是完全相同。但是,实际执行结果(或者能否出现结果)却是有很大的差异。

笔者在开发DBA领域的一个理念是:作为开发人员,对数据库、对数据要有敬畏之心,一个语句发出之前,起码要考虑两个问题:目标数据表的总数据量是多少(投产之后)?你这个操作会涉及到多大的数据量?不同的回答,处理的方案其实是不同的。

更新大表数据,是我们在开发和运维,特别是在数据迁移领域经常遇到的一种场景。上面两个问题的回答是:目标数据表整体就很大,而且更新范围也很大。一个SQL从理论上可以处理。但是在实际中,这种方案会有很多问题。

本篇主要介绍几种常见的大表处理策略,并且分析出他们的优劣。作为我们开发人员和DBA,选取的标准也是灵活的:根据你的操作类型(运维操作还是系统日常作业)、程序运行环境(硬件环境是否支持并行)和程序设计环境(是否可以完全独占所有资源)来综合考量决定。

首先,我们需要准备出一张大表。

1、环境准备

我们选择Oracle 11.2版本进行试验。

SQL> select * from v$version;

BANNER

--------------------------------------------------------------------------------

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

PL/SQL Release 11.2.0.1.0 - Production

CORE 11.2.0.1.0 Production

TNS for Linux: Version 11.2.0.1.0 - Production

NLSRTL Version 11.2.0.1.0 – Production

准备一张大表。

SQL> create table t as select * from dba_objects;

Table created

SQL> insert into t select * from t;

72797 rows inserted

SQL> insert into t select * from t;

145594 rows inserted

(篇幅原因,中间过程略……)

SQL> commit;

Commit complete

SQL> select bytes/1024/1024/1024 from dba_segments where owner='SYS' and segment_name='T';

BYTES/1024/1024/1024

--------------------

1.0673828125

SQL> select count(*) from t;

COUNT(*)

----------

9318016

Executed in 14.711 seconds

数据表T作为数据来源,一共包括9百多万条记录,合计空间1G左右。笔者实验环境是在虚拟机上,一颗虚拟CPU,所以后面进行并行Parallel操作的方案就是示意性质,不具有代表性。

下面我们来看最简单的一种方法,直接update。

2、方法1:直接Update

最简单,也是最容易出问题的方法,就是“不管三七二十一”,直接update数据表。即使很多老程序员和DBA,也总是选择出这样的策略方法。其实,即使结果能出来,也有很大的侥幸成分在其中。

我们首先看笔者的实验,之后讨论其中的原因。先创建一张实验数据表t_target。

SQL> create table t_targettablespace users as select * from t;

Table created

SQL> update t_target set owner=to_char(length(owner));

(长时间等待……)

在等待期间,笔者发现如下几个现象:

ü 数据库服务器运行速度奇慢,很多连接操作速度减缓,一段时间甚至无法登陆;

ü 后台会话等待时间集中在数据读取、log space buffer、空间分配等事件上;

ü 长期等待,操作系统层面开始出现异常。Undo表空间膨胀;

ü 日志切换频繁;

此外,选择这样策略的朋友还可能遇到:前台错误抛出异常、客户端连接被断开等等现象。

笔者遇到这样的场景也是比较纠结,首先,长时间等待(甚至一夜)可能最终没有任何结果。最要命的是也不敢轻易的撤销操作,因为Oracle要进行update操作的回滚动作。一个小时之后,笔者放弃。

updatet_target set owner=to_char(length(owner))

ORA-01013: 用户请求取消当前的操作

(接近一小时未完成)

之后就是相同时间的rollback等待,通常是事务执行过多长时间,回滚进行多长时间。期间,可以通过x$ktuxe后台内部表来观察、测算回滚速度。这个过程中,我们只有“乖乖等待”。

SQL> select KTUXESIZ from x$ktuxe where KTUXESTA<>'INACTIVE';

KTUXESIZ

----------

62877

(……)

SQL> select KTUXESIZ from x$ktuxe where KTUXESTA<>'INACTIVE';

KTUXESIZ

----------

511

综合这种策略的结果通常是:同业抱怨(影响了他们的作业执行)、提心吊胆(不知道执行到哪里了)、资源耗尽(CPU、内存或者IO占到满)、劳而无功(最后还是被rollback)。如果是正式投产环境,还要承担影响业务生产的责任。

我们详细分析一下这种策略的问题:

首先,我们需要承认这种方式的优点,就是简单和片面的高效。相对于在本文中其他介绍的方法,这种方式代码量是最少的。而且,这种方法一次性的将所有的任务提交给数据库SQL引擎,可以最大程度的发挥系统一个方面(CPU、IO或者内存)的能力。

如果我们的数据表比较小,经验值在几万一下,这种方法是比较合适的。我们可以考虑使用。

另一方面,我们要看到Oracle Update的另一个方面,就是Undo、Redo和进程工作负载的问题。熟悉Oracle的朋友们知道,在DML操作的时候,Undo和Redo是非常重要的方面。当我们在Update和Delete数据的时候,数据块被修改之前的“前镜像”就会保存在Undo Tablespace里面。注意:Undo Tablespace是一种特殊的表空间,需要保存在磁盘上。Undo的存在主要是为了支持数据库其他会话的“一致读”操作。只要事务没有被commit或者rollback,Undo数据就会一直保留在数据库中,而且不能被“覆盖”。

Redo记录了进行DML操作的“后镜像”,Redo生成是和我们修改的数据量相关。现实问题要修改多少条记录,生成的Redo总量是不变的,除非我们尝试nologging选项。Redo单个日志成员如果比较小,Oracle应用生成Redo速度比较大。Redo Group切换频度高,系统中就面临着大量的日志切换或者Log Space Buffer相关的等待事件。

如果我们选择第一种方法,Undo表空间就是一个很大的瓶颈。大量的前镜像数据保存在Undo表空间中不能释放,继而不断的引起Undo文件膨胀。如果Undo文件不允许膨胀(autoextend=no),Oracle DML操作会在一定时候报错。即使允许进行膨胀,也会伴随大量的数据文件DBWR写入动作。这也就是我们在进行大量update的时候,在event等待事件中能看到很多的DBWR写入。因为,这些写入中,不一定都是更新你的数据表,里面很多都是Undo表空间写入。

同时,长时间的等待操作,触动Oracle和OS的负载上限,,很多奇怪的事情也可能出现。比如进程僵死、连接被断开。 本条技术文章来源于互联网,如果无意侵犯您的权益请点击此处反馈版权投诉 本文系统来源:php中文网

oracle表update在等待,Oracle中如何更新一张大表记录相关推荐

  1. oracle行锁 查询等待,Oracle 的for update行锁语法

    SELECT...FOR UPDATE 语句的语法如下: SELECT ... FOR UPDATE [OF column_list][WAIT n|NOWAIT][SKIP LOCKED]; 其中: ...

  2. asp.net 2.0中一次性更新所有GRIDVIEW的记录

    在asp.net 2.0中,gridview控件是十分不错的控件.有的时候,可能一个GRIDVIEW控件中 的各行都是文本框,如何一次性更新所有修改过的记录呢?有两种方法,一种是使用sqldataso ...

  3. oracle delete not in 优化,Oracle中的sql语句优化

    1.选择最有效率的表名顺序(只在基于规则的优化器中有效) ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表driving table)将被最先处理,在 ...

  4. oracle 延迟段,DUL 支持Oracle 19c , 如何手动处理延迟段创建的表

    oracle dul是oracle的恢复利器, 它的传奇功能不再解释,但是dul和其它工具一样也是需要段(SEGMENT)块信息恢复数据,但是从oracle 11g开始支持了延迟段创建,那么使用dul ...

  5. oracle撤销段的功能,oracle撤销表空间和回滚段

    /* 撤销表空间 */ 通过使用撤销技术,能够为Oracle数据库提供以下功能: * 使用ROLLBACK语句撤销事务 * 进行数据库恢复 * 提供数据的读一致性 Oracle强烈建议DBA在Orac ...

  6. oracle抽取mysql_oracle到mysql,oracle到oraclel的多表批量数据迁移,定期任务抽取数据-kettle的使用...

    一.背景 上一篇文章(单表数据迁移)用kettle实现了一张表的数据迁移.但实际情况中,数据库会有几百,几千张表,而kettle的表输入和表输出只能选择一张表,我们不可能一个个地填写表名.这时候,我们 ...

  7. Oracle的共享封闭 独占封闭和共享更新封闭 (1)

    前导发端:赛迪网    作者:Andy 设立封闭机制紧张是为了对并发操纵截止控制,对搅扰截止封闭,担保数据的分比喻性和切确性.Oracle数据库封闭体例有三种:共享封闭,独占封闭,共享更新封闭. Or ...

  8. linux update语句,MySQL 多表 update sql语句总结

    MySQL 多表 update 有几种不同的写法. 假定我们有两张表,一张表为Product表存放产品信息,其中有产品价格列Price:另外一张表是ProductPrice表,我们要将ProductP ...

  9. mysql 多表 update sql语句总结

    mysql 多表 update 有几种不同的写法.假定我们有两张表,一张表为Product表存放产品信息,其中有产品价格列Price:另外一张表是ProductPrice表,我们要将ProductPr ...

  10. mysql 联表 update

    假定我们有两张表,一张表为Product表存放产品信息,其中有产品价格列Price:另外一张表是ProductPrice表,我们要将ProductPrice表中的价格字段Price更新为Price表中 ...

最新文章

  1. iphone清理缓存小技巧_那些不为人知的iPhone隐藏小技巧
  2. python批量下载网页文件-超简单超详细python小文件、大文件、批量下载教程
  3. python怎么画圆并改变线条颜色_基于logi的matplotlib中线条颜色的改变
  4. php5.4开启opcache,windows下php5.6启用opcache
  5. 中国最神秘的一所大学,它只存在过8年,却成了永远的第一
  6. 小程序mpvue图片绘制水印_开发笔记:使用 mpvue 开发斗图小程序
  7. linux7配置网卡绑定,CentOS7双网卡绑定配置
  8. 洛谷 P5194 [USACO05DEC]Scales S(DFS)
  9. linux目录与文件,Linux目录与文件基本操作
  10. 【金蝶K3】新/老单据转换流程相关表说明(单据转换流程下推老单,钩稽关系可为严格控制)
  11. 我的第一个app:电信宽带密码一键获取客户端
  12. 5e服务器优化参数,终极优化篇(7700KOC4.8G+1070默认+16GDDR43000)5E练枪图1080P700FPS...
  13. 湖北大学知行学院考研计算机,我院2016届毕业生考研喜创佳绩
  14. MIMO基本技术原理
  15. 如何用 Python 打飞机 ?
  16. 小记--解决方案: rsyslogd cpu占用率高
  17. mysql计算年休假天数_年休假天数计算方法是怎样的
  18. 在国内愚人节可以开的10个玩笑
  19. Android热修复实现一
  20. 成本(CPU Costing)的含义

热门文章

  1. Learn ZYNQ (7)
  2. CityMaker SDK与三维GIS城市
  3. Intel Edison学习笔记(一)—— 刷系统
  4. 【Three.js】模型抗锯齿处理
  5. Dij_heap__前向星。
  6. Linux性能优化之内存优化(二)
  7. 【bzoj2989】数列 KD-tree+旋转坐标系
  8. Java中多态的一些简单理解
  9. Android 怎么使用Bitmap+Canvas 自适应屏幕
  10. iOS 8 Xcode6 设置Launch Image 启动图片转