gpt4 book ai didi

oracle - 为什么 Oracle 在提交期间丢失数据?

转载 作者:行者123 更新时间:2023-12-04 16:14:22 25 4
gpt4 key购买 nike

我有一个相当标准的 SQL 查询,如下所示:

TRUNCATE TABLE TABLE_NAME;
INSERT INTO TABLE_NAME
(
UPRN,
SAO_START_NUMBER,
SAO_START_SUFFIX,
SAO_END_NUMBER,
SAO_END_SUFFIX,
SAO_TEXT,
PAO_START_NUMBER,
PAO_START_SUFFIX,
PAO_END_NUMBER,
PAO_END_SUFFIX,
PAO_TEXT,
STREET_DESCRIPTOR,
TOWN_NAME,
POSTCODE,
XY_COORD,
EASTING,
NORTHING,
ADDRESS
)
SELECT
BASIC_LAND_AND_PROPERTY_UNIT.UPRN,
LAND_AND_PROPERTY_IDENTIFIER.SAO_START_NUMBER AS SAO_START_NUMBER,
LAND_AND_PROPERTY_IDENTIFIER.SAO_START_SUFFIX AS SAO_START_SUFFIX,
LAND_AND_PROPERTY_IDENTIFIER.SAO_END_NUMBER AS SAO_END_NUMBER,
LAND_AND_PROPERTY_IDENTIFIER.SAO_END_SUFFIX AS SAO_END_SUFFIX,
LAND_AND_PROPERTY_IDENTIFIER.SAO_TEXT AS SAO_TEXT,
LAND_AND_PROPERTY_IDENTIFIER.PAO_START_NUMBER AS PAO_START_NUMBER,
LAND_AND_PROPERTY_IDENTIFIER.PAO_START_SUFFIX AS PAO_START_SUFFIX,
LAND_AND_PROPERTY_IDENTIFIER.PAO_END_NUMBER AS PAO_END_NUMBER,
LAND_AND_PROPERTY_IDENTIFIER.PAO_END_SUFFIX AS PAO_END_SUFFIX,
LAND_AND_PROPERTY_IDENTIFIER.PAO_TEXT AS PAO_TEXT,
STREET_DESCRIPTOR.STREET_DESCRIPTOR AS STREET_DESCRIPTOR,
STREET_DESCRIPTOR.TOWN_NAME AS TOWN_NAME,
LAND_AND_PROPERTY_IDENTIFIER.POSTCODE AS POSTCODE,
BASIC_LAND_AND_PROPERTY_UNIT.GEOMETRY AS XY_COORD,
BASIC_LAND_AND_PROPERTY_UNIT.X_COORDINATE AS EASTING,
BASIC_LAND_AND_PROPERTY_UNIT.Y_COORDINATE AS NORTHING,
decode(SAO_START_NUMBER,null,null,SAO_START_NUMBER||SAO_START_SUFFIX||' ')
||decode(SAO_END_NUMBER,null,null,SAO_END_NUMBER||SAO_END_SUFFIX||' ')
||decode(SAO_TEXT,null,null,SAO_TEXT||' ')
||decode(PAO_START_NUMBER,null,null,PAO_START_NUMBER||PAO_START_SUFFIX||' ')
||decode(PAO_END_NUMBER,null,null,PAO_END_NUMBER||PAO_END_SUFFIX||' ')
||decode(PAO_TEXT,null,null,'STREET RECORD',null,PAO_TEXT||' ')
||decode(STREET_DESCRIPTOR,null,null,STREET_DESCRIPTOR||' ')
||decode(POST_TOWN,null,null,POST_TOWN||' ')
||Decode(Postcode,Null,Null,Postcode) As Address
From (Land_And_Property_Identifier
Inner Join Basic_Land_And_Property_Unit
On Land_And_Property_Identifier.Uprn = Basic_Land_And_Property_Unit.Uprn)
Inner Join Street_Descriptor
On Land_And_Property_Identifier.Usrn = Street_Descriptor.Usrn
Where Land_And_Property_Identifier.Postally_Addressable='Y';

如果我在 SQL Developer 中运行此查询,它运行良好,插入了 180 万个功能( session 中的 select count(*) from TABLE_NAME 证实了这一点)。

但是当我运行提交时,数据消失了! select count(*) from TABLE_NAME现在返回 0 个结果。

我们做了很多事情来尝试看看发生了什么:
  • 期间Truncate , 表空间被释放,并在插入期间再次填充。提交期间没有任何变化。这意味着数据在数据库中。
  • 如果我执行完全相同的查询,但使用 and rownum < 100附加到最后,提交有效。同 1000 .
  • 我发现了这个问题:oracle commit kills并让我们的 DBA 尝试“SQL 跟踪”。这产生了一个 > 4GB 的文件,当用 TKPROF 解析它时产生了 120 页的报告,但我们不知道如何阅读它,那里没有明显的错误。
  • 我们的错误日志中没有任何内容。并且在提交过程中显然没有错误。
  • 有一个触发器/序列在此过程中会增加 180 万。

  • 我现在已经重复了大约 4 次,但结果总是一样的。

    所以我的问题很简单 - 提交期间数据发生了什么?我们怎样才能知道?谢谢。

    注意:这在过去运行良好,所以我认为 SQL 本身没有任何问题。

    编辑: 问题已解决 通过从头开始重新创建表。现在,当我插入时,与之前的 2000 秒相比只需要 500 秒。并且提交是即时的;当它被破坏时,提交花了 4000 秒!
    我仍然不知道为什么会发生这种情况。

    对于那些询问,创建表语法:
    CREATE TABLE TABLE_NAME
    (
    ADDRESS VARCHAR2(4000),
    UPRN NUMBER(12),
    SAO_START_NUMBER NUMBER(4),
    SAO_START_SUFFIX VARCHAR2(1),
    SAO_END_NUMBER NUMBER(4),
    SAO_END_SUFFIX VARCHAR2(1),
    SAO_TEXT VARCHAR2(90),
    PAO_START_NUMBER NUMBER(4),
    PAO_START_SUFFIX VARCHAR2(1),
    PAO_END_NUMBER NUMBER(4),
    PAO_END_SUFFIX VARCHAR2(1),
    PAO_TEXT VARCHAR2(90),
    STREET_DESCRIPTOR VARCHAR2(100),
    TOWN_NAME VARCHAR2(30),
    POSTCODE VARCHAR2(8),
    XY_COORD MDSYS.SDO_GEOMETRY,
    EASTING NUMBER(7),
    NORTHING NUMBER(7)
    )

    CREATE INDEX TABLE_NAME_ADD_IDX ON TABLE_NAME (ADDRESS);

    最佳答案

    如果您将交易包装在匿名块中,您还会丢失数据吗?

    我的猜测是您在 SQL Developer 中打开了两个 SQL 窗口,这意味着两个单独的 session 。即在窗口 1 中运行 SQL 代码并提交;在窗口 2 中不会提交在窗口 1 中所做的更改。

    截断表执行隐式提交。因此该表将是空的,直到插入 + 提交完成。

    begin
    execute immediate 'truncate table table_name reuse storage'; --use "reuse" if you know the data will be of similar size
    -- implicit commit has occured and the table is empty for all sessions
    insert into table_name (lots)
    select lots from table2;
    commit;
    end;

    您应该将 truncate 与重用存储一起使用,这样数据库就不会为了在插入中获取相同数量的块而释放所有块。

    如果您希望/需要始终获得可用数据,则更好(但更长)的方法是
    begin
    savepoint letsgo;
    delete from table_name;
    insert into table_name (lots)
    select lots from table2;
    commit;
    exception
    when others then
    rollback to letsgo;
    end;

    关于oracle - 为什么 Oracle 在提交期间丢失数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13009933/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com