0

0

Oracle中如何更新一张大表记录

php中文网

php中文网

发布时间:2016-06-07 16:49:07

|

1135人浏览过

|

来源于php中文网

原创

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

sql语句是一种方便的语言,同样也是一种“迷惑性”的语言。这个主要体现在它的集合操作特性上。无论数据表数据量是1条,还是1亿条,更新的语句都是完全相同。但是,实际执行结果(或者能否出现结果)却是有很大的差异。
 
笔者在开发dba领域的一个理念是:作为开发人员,对数据库、对数据要有敬畏之心,一个语句发出之前,起码要考虑两个问题:目标数据表的总数据量是多少(投产之后)?你这个操作会涉及到多大的数据量?不同的回答,处理的方案其实是不同的。
 
更新大表数据,是我们在开发和运维,特别是在数据迁移领域经常遇到的一种场景。上面两个问题的回答是:目标数据表整体就很大,而且更新范围也很大。一个sql从理论上可以处理。但是在实际中,这种方案会有很多问题。
 
本篇主要介绍几种常见的大表处理策略,并且分析出他们的优劣。作为我们开发人员和dba,选取的标准也是灵活的:根据你的操作类型(运维操作还是系统日常作业)、程序运行环境(硬件环境是否支持并行)和程序设计环境(是否可以完全独占所有资源)来综合考量决定。
 
首先,我们需要准备出一张大表。

1、环境准备

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

SQL> select * from v$version;

 

赣极购物商城网店建站软件系统
赣极购物商城网店建站软件系统

大小仅1兆左右 ,足够轻便的商城系统; 易部署,上传空间即可用,安全,稳定; 容易操作,登陆后台就可设置装饰网站; 并且使用异步技术处理网站数据,表现更具美感。 前台呈现页面,兼容主流浏览器,DIV+CSS页面设计; 如果您有一定的网页设计基础,还可以进行简易的样式修改,二次开发, 发布新样式,调整网站结构,只需修改css目录中的css.css文件即可。 商城网站完全独立,网站源码随时可供您下载

下载

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的负载上限,,很多奇怪的事情也可能出现。比如进程僵死、连接被断开。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
AO3官网入口与中文阅读设置 AO3网页版使用与访问
AO3官网入口与中文阅读设置 AO3网页版使用与访问

本专题围绕 Archive of Our Own(AO3)官网入口展开,系统整理 AO3 最新可用官网地址、网页版访问方式、正确打开链接的方法,并详细讲解 AO3 中文界面设置、阅读语言切换及基础使用流程,帮助用户稳定访问 AO3 官网,高效完成中文阅读与作品浏览。

3

2026.02.02

主流快递单号查询入口 实时物流进度一站式追踪专题
主流快递单号查询入口 实时物流进度一站式追踪专题

本专题聚合极兔快递、京东快递、中通快递、圆通快递、韵达快递等主流物流平台的单号查询与运单追踪内容,重点解决单号查询、手机号查物流、官网入口直达、包裹进度实时追踪等高频问题,帮助用户快速获取最新物流状态,提升查件效率与使用体验。

0

2026.02.02

Golang WebAssembly(WASM)开发入门
Golang WebAssembly(WASM)开发入门

本专题系统讲解 Golang 在 WebAssembly(WASM)开发中的实践方法,涵盖 WASM 基础原理、Go 编译到 WASM 的流程、与 JavaScript 的交互方式、性能与体积优化,以及典型应用场景(如前端计算、跨平台模块)。帮助开发者掌握 Go 在新一代 Web 技术栈中的应用能力。

1

2026.02.02

PHP Swoole 高性能服务开发
PHP Swoole 高性能服务开发

本专题聚焦 PHP Swoole 扩展在高性能服务端开发中的应用,系统讲解协程模型、异步IO、TCP/HTTP/WebSocket服务器、进程与任务管理、常驻内存架构设计。通过实战案例,帮助开发者掌握 使用 PHP 构建高并发、低延迟服务端应用的工程化能力。

1

2026.02.02

Java JNI 与本地代码交互实战
Java JNI 与本地代码交互实战

本专题系统讲解 Java 通过 JNI 调用 C/C++ 本地代码的核心机制,涵盖 JNI 基本原理、数据类型映射、内存管理、异常处理、性能优化策略以及典型应用场景(如高性能计算、底层库封装)。通过实战示例,帮助开发者掌握 Java 与本地代码混合开发的完整流程。

1

2026.02.02

go语言 注释编码
go语言 注释编码

本专题整合了go语言注释、注释规范等等内容,阅读专题下面的文章了解更多详细内容。

61

2026.01.31

go语言 math包
go语言 math包

本专题整合了go语言math包相关内容,阅读专题下面的文章了解更多详细内容。

52

2026.01.31

go语言输入函数
go语言输入函数

本专题整合了go语言输入相关教程内容,阅读专题下面的文章了解更多详细内容。

25

2026.01.31

golang 循环遍历
golang 循环遍历

本专题整合了golang循环遍历相关教程,阅读专题下面的文章了解更多详细内容。

10

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号