oracle容错,Oracle DML容错处理方法

关于DML Error Logging效率的问题,摘自网上一篇文章,作为单独一篇说明,原文如下:

DML Error Logging in Oracle 10g Database Release 2

In some situations the most obvious solution to a problem is a DML statement (INSERT ... SELECT,UPDATE,DELETE), but you may choose to avoid DML because of the way it reacts to exceptions. By default, when a DML statement fails the whole statement is rolled back, regardless of how many rows were processed successfully before the error was detected. In the past, the only way around this problem was to process each row individually, preferably with a bulk operation usingFORALLand theSAVE EXCEPTIONSclause. In Oracle 10g Database Release 2, the DML error logging feature has been introduced to solve this problem. Adding the appropriateLOG ERRORSclause on to most INSERT, UPDATE, MERGE and DELETE statements enables the operations to complete, regardless of errors. This article presents an overview of the DML error logging functionality, with examples of each type of DML statement.

Syntax

Restrictions

Sample Schema

Insert

Update

Merge

Delete

Performance

Syntax

The syntax for the error logging clause is the same for INSERT, UPDATE, MERGE and DELETE statements.

LOG ERRORS [INTO [schema.]table] [('simple_expression')] [REJECT LIMIT integer|UNLIMITED]

The optionalINTOclause allows you to specify the name of the error logging table. If you omit this clause, the the first 25 characters of the base table name are used along with the "ERR$_" prefix.

Thesimple_expressionis used to specify a tag that makes the errors easier to identify. This might be a string or any function whose result is converted to a string.

TheREJECT LIMITis used to specify the maximum number of errors before the statement fails. The default value is 0 and the maximum values is the keywordUNLIMITED. For parallel DML operations, the reject limit is applied to each parallel server.

Restrictions

The DML error logging functionality is not invoked when:

Deferred constraints are violated.

Direct-path INSERT or MERGE operations raise unique constraint or index violations.

UPDATE or MERGE operations raise a unique constraint or index violation.

In addition, the tracking of errors in LONG, LOB and object types is not supported, although a table containing these columns can be the target of error logging.

Sample Schema

This following code creates and populates the tables necessary to run the example code in this article.

-- Create and populate a source table.

CREATE TABLE source (

id NUMBER(10) NOT NULL,

code VARCHAR2(10),

description VARCHAR2(50),

CONSTRAINT source_pk PRIMARY KEY (id)

);

DECLARE

TYPE t_tab IS TABLE OF source%ROWTYPE;

l_tab t_tab := t_tab();

BEGIN

FOR i IN 1 .. 100000 LOOP

l_tab.extend;

l_tab(l_tab.last).id := i;

l_tab(l_tab.last).code := TO_CHAR(i);

l_tab(l_tab.last).description := 'Description for ' || TO_CHAR(i);

END LOOP;

-- For a possible error condition.

l_tab(1000).code := NULL;

l_tab(10000).code := NULL;

FORALL i IN l_tab.first .. l_tab.last

INSERT INTO source VALUES l_tab(i);

COMMIT;

END;

/

EXEC DBMS_STATS.gather_table_stats(USER, 'source', cascade => TRUE);

-- Create a destination table.

CREATE TABLE dest (

id NUMBER(10) NOT NULL,

code VARCHAR2(10) NOT NULL,

description VARCHAR2(50),

CONSTRAINT dest_pk PRIMARY KEY (id)

);

-- Create a dependant of the destination table.

CREATE TABLE dest_child (

id NUMBER,

dest_id NUMBER,

CONSTRAINT child_pk PRIMARY KEY (id),

CONSTRAINT dest_child_dest_fk FOREIGN KEY (dest_id) REFERENCES dest(id)

);

Notice that theCODEcolumn is optional in theSOURCEtable and mandatory in theDESTtable.

Once the basic tables are in place we can create a table to hold the DML error logs for theDEST. A log table must be created for every base table that requires the DML error logging functionality. This can be done manually or with theCREATE_ERROR_LOGprocedure in theDBMS_ERRLOGpackage, as shown below.

-- Create the error logging table.

BEGIN

DBMS_ERRLOG.create_error_log (dml_table_name => 'dest');

END;

/

PL/SQL procedure successfully completed.

SQL>

The owner, name and tablespace of the log table can be specified, but by default it is created in the current schema, in the default tablespace with a name that matches the first 25 characters of the base table with the "ERR$_" prefix.

SELECT owner, table_name, tablespace_name

FROM all_tables

WHERE owner = 'TEST';

OWNER TABLE_NAME TABLESPACE_NAME

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

TEST DEST USERS

TEST DEST_CHILD USERS

TEST ERR$_DEST USERS

TEST SOURCE USERS

4 rows selected.

SQL>

The structure of the log table includes maximum length and datatype independent versions of all available columns from the base table, as seen below.

SQL> DESC err$_dest

Name Null? Type

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

ORA_ERR_NUMBER$ NUMBER

ORA_ERR_MESG$ VARCHAR2(2000)

ORA_ERR_ROWID$ ROWID

ORA_ERR_OPTYP$ VARCHAR2(2)

ORA_ERR_TAG$ VARCHAR2(2000)

ID VARCHAR2(4000)

CODE VARCHAR2(4000)

DESCRIPTION VARCHAR2(4000)

SQL>

Insert

When we built the sample schema we noted that theCODEcolumn is optional in theSOURCEtable, but mandatory in thDESTtable. When we populated theSOURCEtable we set the code to NULL for two of the rows. If we try to copy the data from theSOURCEtable to theDESTtable we get the following result.

INSERT INTO dest

SELECT *

FROM source;

SELECT *

*

ERROR at line 2:

ORA-01400: cannot insert NULL into ("TEST"."DEST"."CODE")

SQL>

The failure causes the whole insert to roll back, regardless of how many rows were inserted successfully. Adding the DML error logging clause allows us to complete the insert of the valid rows.

INSERT INTO dest

SELECT *

FROM source

LOG ERRORS INTO err$_dest ('INSERT') REJECT LIMIT UNLIMITED;

99998 rows created.

SQL>

The rows that failed during the insert are stored in theERR$_DESTtable, along with the reason for the failure.

COLUMN ora_err_mesg$ FORMAT A70

SELECT ora_err_number$, ora_err_mesg$

FROM err$_dest

WHERE ora_err_tag$ = 'INSERT';

ORA_ERR_NUMBER$ ORA_ERR_MESG$

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

1400 ORA-01400: cannot insert NULL into ("TEST"."DEST"."CODE")

1400 ORA-01400: cannot insert NULL into ("TEST"."DEST"."CODE")

2 rows selected.

SQL>

Update

The following code attempts to update theCODEcolumn for 10 rows, setting it to itself for 8 rows and to the value NULL for 2 rows.

UPDATE dest

SET code = DECODE(id, 9, NULL, 10, NULL, code)

WHERE id BETWEEN 1 AND 10;

*

ERROR at line 2:

ORA-01407: cannot update ("TEST"."DEST"."CODE") to NULL

SQL>

As expected, the statement fails because theCODEcolumn is mandatory. Adding the DML error logging clause allows us to complete the update of the valid rows.

UPDATE dest

SET code = DECODE(id, 9, NULL, 10, NULL, code)

WHERE id BETWEEN 1 AND 10

LOG ERRORS INTO err$_dest ('UPDATE') REJECT LIMIT UNLIMITED;

8 rows updated.

SQL>

The rows that failed during the update are stored in theERR$_DESTtable, along with the reason for the failure.

COLUMN ora_err_mesg$ FORMAT A70

SELECT ora_err_number$, ora_err_mesg$

FROM err$_dest

WHERE ora_err_tag$ = 'UPDATE';

ORA_ERR_NUMBER$ ORA_ERR_MESG$

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

1400 ORA-01400: cannot insert NULL into ("TEST"."DEST"."CODE")

1400 ORA-01400: cannot insert NULL into ("TEST"."DEST"."CODE")

2 rows selected.

SQL>

Merge

The following code deletes some of the rows from theDESTtable, then attempts to merge the data from theSOURCEtable into theDESTtable.

DELETE FROM dest

WHERE id > 50000;

MERGE INTO dest a

USING source b

ON (a.id = b.id)

WHEN MATCHED THEN

UPDATE SET a.code = b.code,

a.description = b.description

WHEN NOT MATCHED THEN

INSERT (id, code, description)

VALUES (b.id, b.code, b.description);

*

ERROR at line 9:

ORA-01400: cannot insert NULL into ("TEST"."DEST"."CODE")

SQL>

As expected, the merge operation fails and rolls back. Adding the DML error logging clause allows the merge operation to complete.

MERGE INTO dest a

USING source b

ON (a.id = b.id)

WHEN MATCHED THEN

UPDATE SET a.code = b.code,

a.description = b.description

WHEN NOT MATCHED THEN

INSERT (id, code, description)

VALUES (b.id, b.code, b.description)

LOG ERRORS INTO err$_dest ('MERGE') REJECT LIMIT UNLIMITED;

99998 rows merged.

SQL>

The rows that failed during the update are stored in theERR$_DESTtable, along with the reason for the failure.

COLUMN ora_err_mesg$ FORMAT A70

SELECT ora_err_number$, ora_err_mesg$

FROM err$_dest

WHERE ora_err_tag$ = 'MERGE';

ORA_ERR_NUMBER$ ORA_ERR_MESG$

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

1400 ORA-01400: cannot insert NULL into ("TEST"."DEST"."CODE")

1400 ORA-01400: cannot insert NULL into ("TEST"."DEST"."CODE")

2 rows selected.

SQL>

Delete

TheDEST_CHILDtable has a foreign key to theDESTtable, so if we add some data to it would would expect an error if we tried to delete the parent rows from theDESTtable.

INSERT INTO dest_child (id, dest_id) VALUES (1, 100);

INSERT INTO dest_child (id, dest_id) VALUES (2, 101);

With the child data in place we ca attempt to delete th data from theDESTtable.

DELETE FROM dest;

*

ERROR at line 1:

ORA-02292: integrity constraint (TEST.DEST_CHILD_DEST_FK) violated - child record found

SQL>

As expected, the delete operation fails. Adding the DML error logging clause allows the delete operation to complete.

DELETE FROM dest

LOG ERRORS INTO err$_dest ('DELETE') REJECT LIMIT UNLIMITED;

99996 rows deleted.

SQL>

The rows that failed during the delete operation are stored in theERR$_DESTtable, along with the reason for the failure.

COLUMN ora_err_mesg$ FORMAT A69

SELECT ora_err_number$, ora_err_mesg$

FROM err$_dest

WHERE ora_err_tag$ = 'DELETE';

ORA_ERR_NUMBER$ ORA_ERR_MESG$

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

2292 ORA-02292: integrity constraint (TEST.DEST_CHILD_DEST_FK) violated -

child record found

2292 ORA-02292: integrity constraint (TEST.DEST_CHILD_DEST_FK) violated -

child record found

2 rows selected.

SQL>

Performance

The performance of DML error logging depends on the way it is being used and what version of the database you use it against. Prior to Oracle 12c, you will probably only use DML error logging during direct path loads, since conventional path loads become very slow when using it. The following example displays this, but before we start we will need to remove the extra dependency table.

DROP TABLE dest_child PURGE;

Truncate the destination table and run a conventional path load using DML error logging, using SQL*Plus timing to measure the elapsed time.

SET TIMING ON

TRUNCATE TABLE dest;

INSERT INTO dest

SELECT *

FROM source

LOG ERRORS INTO err$_dest ('INSERT NO-APPEND') REJECT LIMIT UNLIMITED;

99998 rows created.

Elapsed: 00:00:08.61

SQL>

Next, repeat the test using a direct path load this time.

TRUNCATE TABLE dest;

INSERT /*+ APPEND */ INTO dest

SELECT *

FROM source

LOG ERRORS INTO err$_dest ('INSERT APPEND') REJECT LIMIT UNLIMITED;

99998 rows created.

Elapsed: 00:00:00.38

SQL>

Finally, perform the same load usingFORALL ... SAVE EXCEPTIONSmethod.

TRUNCATE TABLE dest;

DECLARE

TYPE t_tab IS TABLE OF dest%ROWTYPE;

l_tab t_tab;

l_start PLS_INTEGER;

CURSOR c_source IS

SELECT * FROM source;

ex_dml_errors EXCEPTION;

PRAGMA EXCEPTION_INIT(ex_dml_errors, -24381);

BEGIN

OPEN c_source;

LOOP

FETCH c_source

BULK COLLECT INTO l_tab LIMIT 1000;

EXIT WHEN l_tab.count = 0;

BEGIN

FORALL i IN l_tab.first .. l_tab.last SAVE EXCEPTIONS

INSERT INTO dest VALUES l_tab(i);

EXCEPTION

WHEN ex_dml_errors THEN

NULL;

END;

END LOOP;

CLOSE c_source;

END;

/

PL/SQL procedure successfully completed.

Elapsed: 00:00:01.01

SQL>

From this we can see that DML error logging is very fast for direct path loads, but does not perform well for conventional path loads. In fact, it performs significantly worse than theFORALL ... SAVE EXCEPTIONSmethod.

The relative performance of these methods depends on the database version. The following table shows the results of the previous tests against a number of database versions. They are run on different servers, so don't compare version-to-version. Look at the comparison between the methods within a version.

10.2.0.4 11.2.0.3 11.2.0.4 12.1.0.1

======== ======== ======== ========

DML Error Logging : 07.62 08.61 04.82 00.94

DML Error Logging (APPEND) : 00.86 00.38 00.85 01.07

FORALL ... SAVE EXCEPTIONS : 01.15 01.01 00.94 01.37

同样的方式不同数据库版本性能可能不同,同版本数据库下,使用直接路径加

0b1331709591d260c1c78e86d0c51c18.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/265394.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图解快速区别——串口、COM口、UART、TTL、RS-232、RS-485

参考:串口、COM口、UART口, TTL、RS-232、RS-485区别详解 作者:flyingju 发布时间: 2017-09-16 10:30:31 网址:https://blog.csdn.net/zhuyongxin_6688/article/details/78001767 目录串口名词区分COM口串口UARTD型9针串口USB转TT…

这份代码是不是应该有BUG!!

为什么80%的码农都做不了架构师?>>> #include"stdio.h" #include"stdlib.h" #include"math.h" #include"io.h" #include"time.h" #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #de…

NXP(I.MX6uLL) UART串口通信原理————这个未复习

参考:Linux NXP (I.MX6uLL) UART串口通信原理 作者:一只青木呀 发布时间: 2020-09-20 16:48:33 网址:https://blog.csdn.net/weixin_45309916/article/details/108694634 目录1、UART简介1.1、UART串口通讯…

linux内核pwn,Linux Kernel Pwn 学习笔记 (UAF)

原标题:Linux Kernel Pwn 学习笔记 (UAF)本文为看雪论坛优秀文章看雪论坛作者ID:Vinadiak0x01 背景知识UAF漏洞:UAF 漏洞是当我们 free 掉某个指针变量所指向的堆块的时候,未将该指针变量置0,导致该指针依然指着该堆块…

NXP(I.MX6uLL)DDR3实验——DDR发展历史

目录何为RAM 和ROMSRAM 简介①、地址线②、数据线③、控制线SDRAM 简介①、控制线(时钟、片选)②、A10 地址线③、地址线④、BANK 选择线⑤、BANK 区域⑥、数据线⑦、高低字节选择DDR 简介①、控制线②、地址线③、BANK 选择线④、BANK 区域⑤、数据线⑥、数据选通引脚⑦、数据…

超赞!12套你没见过的社交媒体 社交网站图标

如今,社交网络成为我们信息获取和传播的重要途径,很多网站都有把内容分享到社交媒体的功能。社交媒体图标作为向用户传递信息的重要媒介,不管是在网页还是 Web 应用程序中都非常需要。今天这篇文章和大家分享12套你没见过的社交媒体 & 社…

I2C实验

参考:I2C 总线协议详解 作者:一只青木呀 发布时间:2020-09-21 11:41:25 网址:https://blog.csdn.net/weixin_45309916/article/details/108705297 目录I2C 简介I2C 协议I2C协议有关术语1、起始位2、停止位3、数据传输4、应答信号5…

linux安装ffmpeg版本太多,Linux安装FFmpeg的方法

FFmpeg是一款优秀的播放器解码插件,可以跨平台,有不同平台的版本,对于解码,编码和录制以及转换作用的很多的软件都是使用FFmpeg的插件来实现的.FFmpeg:https://www.ffmpeg.org/download.html安装方法:#wget…

官方系统镜像烧写(windows下使用OTG)

目录OTG系统烧写为什么能通过VBS将系统烧写进去呢?OTG系统烧写 选择对应的烧写工具,USB_OTG线连接好,双击即可进行烧写。 注意: 当然也可以烧写到SD卡里面。前面我们烧写裸机代码都是选择从SD卡启动。Mfgtool这个工具先向板子下载…

SQL Server中通用数据库角色权限的处理详解

SQL Server中通用数据库角色权限的处理详解 前言 安全性是所有数据库管理系统的一个重要特征。理解安全性问题是理解数据库管理系统安全性机制的前提。 最近和同事在做数据库权限清理的事情,主要是删除一些账号;取消一些账号的较大的权限等,例…

linux之xargs命令用途

实现文件删除的方法大致有以下几种:1.rm find /a -type f 2.find /a -type f -exec|-ok rm -rf { } \;3.find /a -type f -exec|-ok rm -rf { } ;本例中xargs将find产生的长串文件列表拆散成多个子串,然后…

什么是U-Boot以及如何下载U-Boot源码

参考:什么是U-Boot以及如何下载U-Boot源码? 作者:一只青木呀 发布时间: 2020-10-20 11:05:59 网址:https://blog.csdn.net/weixin_45309916/article/details/109176510 目录前言系统的启动过程uboot简介uboot源码下载选…

linux系统重装win系统教程,Win10如何重装linux系统 Win10重装linux系统教程

Windows10如何重装linux系统?下面小编就给大家介绍一下Win10重装linux系统教程。1、我们按下wini打开设置 后点击【更新和安全】->【windows更新】;2、我们在左侧点击【针对开发人员】,在右侧点击【发开人员模式】;3、我们按winx键->选择【程序和功能】;4、我…

Uboot初次编译、烧写、启动(启动界面log简析)

目录U-Boot 初次编译U-Boot 烧写与启动上述笔记第三点就是建立shell脚本实现的 第四点就是修改Makefile文件实现的,下面均有实现步骤讲解。 U-Boot 初次编译 先编译体验一下正点原子提供的UBOOT。 首先在Ubuntu 中安装ncurses 库,否则编译会报错&#…

360 linux 扩展文件夹,360签具名工Linux下载0907 官方版

腾牛网提供的这款360签名工具Linux版,共有两个版本,分别是图形界面版和命令行界面版,两种选择为apk签名具有一样的正版效果。相关下载:360加固助手pc端Linux签名工具使用流程(图形界面)使用方法:一、准备工作&#xff…

锁优化

前言 高效并发是从JDK1.5到JDK1.6的一个重要改进,HotSpot虚拟机开发团队在这个版本上花费了大量的精力去实现各种锁优化技术,如适应性自旋、锁消除、锁粗化、轻量级锁和偏向锁等,这些技术都是为了在线程之间高效的共享数据,以及解…

WPF--ComboBox数据绑定

0-在ComboBox中显示图片&#xff1a; <ComboBox Height"33" HorizontalAlignment"Right" Margin"0,94,31,0" x:Name"comboBox1" VerticalAlignment"Top" Width"142" SelectedIndex"0"> <Co…

U-Boot源码目录分析(VScode工程创建及文件夹过滤)

参考&#xff1a;U-Boot工程目录介绍 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-10-21 14:47:30 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/109199081 目录0、Uboot下载编译VScode工程创建及文件夹过滤2、重要文件2.1、arch文件夹&…

Spring Security 案例实现和执行流程剖析

在线演示 演示地址&#xff1a;http://139.196.87.48:9002/kitty 用户名&#xff1a;admin 密码&#xff1a;admin Spring Security Spring Security 是 Spring 社区的一个顶级项目&#xff0c;也是 Spring Boot 官方推荐使用的安全框架。除了常规的认证&#xff08;Authentica…

Ubuntu用户与用户组

目录Ubuntu用户与用户组创建用户和用户组Ubuntu用户与用户组 创建用户和用户组