【问题标题】:automating rollback script oracle自动回滚脚本oracle
【发布时间】:2012-02-17 00:03:45
【问题描述】:

在向非开发数据库发布数据库代码时,我使用这种方法 - 我创建发布 sqlplus 脚本,该脚本依次运行多个 create table/view/sequence/package/etc 语句。如果在部署或进一步使用期间需要,我还应该创建执行 drop 和其他语句的回滚脚本。但是手动创建回滚脚本总是很烦人。 IE。 - 当我把

alter table table_a add column some_column number(5);

进入发布脚本。我必须放

alter table table_a drop column some_column;

进入回滚脚本。反之亦然。

有没有办法优化(或半优化)它?也许有一些 Java/Python/etc 库允许将 ddl 语句解析为逻辑部分?

也许有一些更好的方法来发布/回滚 pl/sql 代码?

【问题讨论】:

  • 你看过Oracle闪回吗?我认为您可以撤消 DDL,但不能 100% 确定。也许有人可以对此发表评论。
  • 闪回,据我所知,是针对一些不同的解决方案。它还回滚数据。 IE。 - a 已发布(向表中添加列),然后用户已将一些数据插入到此表中,然后用户决定不应立即发布基于此列的功能,而应在以后的版本中发布。如果我使用闪回 - 用户插入的数据将与我添加的列一起被删除。但我只想删除列,留下数据。

标签: oracle plsql release-management


【解决方案1】:

DBMS_METADATA_DIFF 和一些元数据查询可以自动执行此过程。

此示例演示了 6 种类型的更改:1) 添加列 2) 递增序列 3) 删除表 4) 创建表 5) 更改视图 6) 分配范围。

create table user1.add_column(id number);
create table user2.add_column(id number);
alter table user2.add_column add some_column number(5);

create sequence user1.increment_sequence nocache;
select user1.increment_sequence.nextval from dual;
select user1.increment_sequence.nextval from dual;
create sequence user2.increment_sequence nocache;
select user2.increment_sequence.nextval from dual;

create table user1.drop_table(id number);

create table user2.create_table(id number);

create view user1.change_view as select 1 a from dual;
create view user2.change_view as select 2 a from dual;

create table user1.allocate_extent(id number);
create table user2.allocate_extent(id number);
insert into user2.allocate_extent values(1);
rollback;

您说得对,DBMS_METADATA_DIFF 不适用于CREATE 或DROP。尝试区分仅存在于一个模式中的对象将生成错误消息 像这样:

ORA-31603: object "EXTRA_TABLE" of type TABLE not found in schema "USER1"
ORA-06512: at "SYS.DBMS_METADATA", line 7944
ORA-06512: at "SYS.DBMS_METADATA_DIFF", line 712

然而,删除和添加对象可能很容易使用以下脚本编写:

--Dropped objects
select 'DROP '||object_type||' USER1.'||object_name v_sql
from
(
    select object_name, object_type from dba_objects where owner = 'USER1'
    minus
    select object_name, object_type from dba_objects where owner = 'USER2'
);

V_SQL
-----
DROP TABLE USER1.DROPPED_TABLE

--Added objects
select dbms_metadata.get_ddl(object_type, object_name, 'USER2') v_sql
from
(
    select object_name, object_type from dba_objects where owner = 'USER2'
    minus
    select object_name, object_type from dba_objects where owner = 'USER1'
);

V_SQL
-----
  CREATE TABLE "USER2"."CREATED_TABLE" 
   (    "ID" NUMBER
   ) SEGMENT CREATION DEFERRED 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
 NOCOMPRESS LOGGING
  TABLESPACE "USERS" 

可以使用如下 SQL 语句来处理变更:

select object_name, object_type, dbms_metadata_diff.compare_alter(
    object_type => object_type,
    name1 => object_name,
    name2 => object_name,
    schema1 => 'USER2',
    schema2 => 'USER1',
    network_link1 => 'MYSELF',
    network_link2 => 'MYSELF') difference
from
(
    select object_name, object_type from dba_objects where owner = 'USER1'
    intersect
    select object_name, object_type from dba_objects where owner = 'USER2'
) objects;


OBJECT_NAME         OBJECT_TYPE    DIFFERENCE
-----------         -----------    ----------
ADD_COLUMN          TABLE          ALTER TABLE "USER2"."ADD_COLUMN" DROP ("SOME_COLUMN")
ALLOCATE_EXTENT     TABLE          -- ORA-39278: Cannot alter table with segments to segment creation deferred.
CHANGE_VIEW         VIEW           -- ORA-39308: Cannot alter attribute of view: SUBQUERY
INCREMENT_SEQUENCE  SEQUENCE       ALTER SEQUENCE "USER2"."INCREMENT_SEQUENCE" RESTART START WITH 3

关于这些结果的一些说明:

  • ADD_COLUMN 按预期工作。
  • ALLOCATE_EXTENT 可能是误报,我怀疑您是否关心延迟段的创建。它不太可能影响您的系统。
  • CHANGE_VIEW 根本不起作用。但与之前的元数据查询一样,应该有一种相对简单的方法来使用 DBA_VIEWS 构建此脚本。
  • INCREMENT_SEQUENCE 效果太好了。大多数时候,应用程序并不关心序列值。但有时当事情不同步时,你需要改变它们。这个RESTART START WITH 语法非常有用。您不需要删除或重新创建索引,也不需要多次弄乱increment by。此语法不在12c manual 中。事实上,我在谷歌的任何地方都找不到它。看起来这个包使用了未记录的功能。

其他一些注意事项:

  • 包有时会很慢。
  • 如果服务器上的网络链接有问题,您需要通过本地实例运行它,并链接到两台服务器。
  • 可能存在误报。有时它会返回一行,其中只有一个空格。

这个过程可以完全自动化。但基于上述问题,以及我对所有此类自动化工具的经验,你不应该 100% 相信它。

【讨论】:

  • 谢谢!我会试试看。确保回滚脚本审查应始终进行。我只是在谈论自动化它。我如何从 DBMS_METADATA_DIFF 的文档中看到,它只能处理 alter 语句,对吗?那么处理创建/删除表/序列/视图等呢?你在现实生活中使用过它吗?
  • 查看我修改后的答案。我认为使用这个包和其他一些元数据查询可以得到你想要的。 4 个查询可以让您完成大约 99% 的任务。但最后 1% 可能非常困难。我在真实系统上使用过这个特性,但只是为了验证已知的变化。我从未运行过实际的脚本。
  • 谢谢!这不是我想要的,因为没有适用于所有情况的程序,您还应该决定使用什么(我认为这并不比手动编写回滚更容易)。但由于没有其他答案,在我看来,它是唯一一种可能的变体。我认为唯一可能的方法是编写解析输入的应用程序 - 决定它是什么类型的 ddl 并生成 roolback 语句。
猜你喜欢
  • 2020-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
  • 1970-01-01
  • 2011-03-07
  • 1970-01-01
相关资源
最近更新 更多