百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

Oracle 中 drop_column 的几种方式和风险

mhr18 2024-10-12 04:32 15 浏览 0 评论

原文链接: https://www.modb.pro/db/24497(复制链接至浏览器,即可查看)

你是否足够了解在生产环境上执行drop column操作或者类似的DDL操作有多危险?

生产环境的一张大表上执行了一个 drop column,导致业务停止运行几个小时,这样的事情发生任何一位 DBA 身上,都会有一种深秋的悲凉。你是否足够了解在生产环境上执行 drop column 操作或者类似的DDL操作有多危险?本文通过一组模拟测试,观察几种不同的 drop column 方式对业务的影响。

测试脚本准备

create table t_test_col(
ids number,
dates date,
vara varchar2(2000),
varb varchar2(2000),
varc varchar2(2000),
vard varchar2(2000)
)
PARTITION BY RANGE (dates) INTERVAL (numtodsinterval(1, 'day'))
(partition part_t01 values less than(to_date('2000-11-01', 'yyyy-mm-dd')));
;
--插入200万测试数据
begin
  for i in 1..2000000 loop
    insert into t_test_col values(i,sysdate-mod(i,100),'abc_aaaa','abc_bbbb','abc_cccc','abc_dddd');
    if mod(i,1000)=0 then
      commit;
    end if;
  end loop;
  commit;
end;
--业务模拟程序1,每0.1秒执行一次插入,并记录日志表
declare
  l_cnt integer;
  l_var varchar2(2000);
begin
  for i in 1..10000 loop
    begin
      insert into t_test_col(ids,dates,vara) values(i,sysdate,'test_aaaa');
      rollback;
      insert into t_log(dates,vars) values(systimestamp,'INSERT--ok');
      commit;
    exception
      when others then
        l_var:=substr(sqlerrm,1,1000);
        insert into t_log(dates,vars) values(systimestamp,'INSERT--'||l_var);
        commit;
    dbms_lock.sleep(0.1);
  end loop;
end;
--业务模拟程序2,每0.1秒执行一次查询,并记录日志表
declare
 l_cnt integer;
  l_var varchar2(2000);
begin
for i in 1..10000 loop
    begin
      SELECT COUNT(1) INTO L_CNT from t_test_col where rownum=1;
      insert into t_log(dates,vars) values(systimestamp,'SELECT--ok');
      commit;
    exception
      when others then
        l_var:=substr(sqlerrm,1,1000);
        insert into t_log(dates,vars) values(systimestamp,'SELECT--'||l_var);
        commit;
    end;
    dbms_lock.sleep(0.1);
  end loop;
end;

场景一:直接drop column

运行业务模拟程序,开始正常插入日志,然后删除大表的字段。

alter table t_test_col drop column vard;

影响范围:

  1. drop column操作耗时30多秒;
  2. insert 语句在drop column完成之前无法执行,等待事件为enq:TM-contention;
  3. select不受影响。

场景二:先set unused然后再drop

alter table t_test_col set unused column vard;
alter table t_test_col drop unused columns;

set unused仅更新表的数据字典,先将字段置为不可用状态,drop unused操作时才更新数据内容。

影响范围:与场景一完全相同。

注意上述两种方式还会遇到一个非常麻烦的问题,在执行drop column的过程中,需要修改每一行数据,运行时间往往特别长,这会消耗大量的undo表空间,如果表特别大,操作时间足够长,undo表空间会全部耗尽。为了解决这个问题,有了第三种场景。

场景三:先set unused然后再drop column checkpoint

alter table t_test_col set unused column vard;
alter table t_test_col drop unused columns checkpoint 1000;

drop unused columns checkpoint操作是每删除多少条记录,做一次提交,避免UNDO爆掉。这是一个好的解决思路,但是它带来的风险也是非常大的。这个操作在间隔分区上执行会命中BUG:20598042,ALTER TABLE DROP COLUMN … CHECKPOINT on an INTERVAL PARTITIONED table fails with ORA-600 [17016]

执行结果是:

  1. drop column checkpoint操作会报ORA-600[17016]错误;
  2. 插入和查询操作,在drop过程以及drop报错之后,均抛出ORA-12986异常;
  3. 在打补丁修复bug之前,这个表将无法正常使用。

换成普通分区表,先set unused然后再drop column checkpoint

alter table t_test_col_2 set unused column vard;
alter table t_test_col_2 drop unused columns checkpoint 1000;

影响范围:

  1. insert 和select在drop column操作完成之前均无法执行;
  2. 等待事件为library cache lock。

场景四: 使用DBMS_REDEFINITION包删除字段

create table T_TEST_COL_3
as select ids,dates,vara,varb,varc,vard  from t_test_col_2;

create table T_TEST_COL_mid
(
  ids   NUMBER,
  dates DATE,
  vara  VARCHAR2(2000),
  varb  VARCHAR2(2000),
  varc  VARCHAR2(2000)
);

BEGIN
   DBMS_REDEFINITION.CAN_REDEF_TABLE('ENMOTEST','T_TEST_COL_3', DBMS_REDEFINITION.CONS_USE_ROWID);
END;
/
BEGIN
   DBMS_REDEFINITION.START_REDEF_TABLE(
         uname => 'ENMOTEST',
         orig_table => 'T_TEST_COL_3',
         int_table => 'T_TEST_COL_MID',
         col_mapping => 'IDS IDS, DATES DATES, VARA VARA,VARB VARB,VARC VARC',
         options_flag => DBMS_REDEFINITION.CONS_USE_ROWID);
END;
/

DECLARE
    error_count pls_integer := 0;
BEGIN
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('ENMOTEST',
                   'T_TEST_COL_3',
                   'T_TEST_COL_MID',
                    dbms_redefinition.cons_orig_params ,
                   TRUE,
                   TRUE,
                   TRUE,
                   FALSE,
                   error_count);
    DBMS_OUTPUT.PUT_LINE('errors := ' || TO_CHAR(error_count));
END;
/
BEGIN dbms_redefinition.finish_redef_table('ENMOTEST','T_TEST_COL_3','T_TEST_COL_MID');  END;
DROP TABLE T_TEST_COL_MID;

影响范围:

  1. 中间表的大小与原表相当(需要耗费很大的空间及产生大量归档日志);
  2. 先阻塞insert,再阻塞select,时间一秒多,等待事件中能看到只有非常短暂的TM锁表操作。

场景五: 中断测试

在场景一到场景三的执行过程中,突然中断会话,观察中断后的情况:

  1. 直接drop column,中断后表可正常使用,字段仍然还在;
  2. 先set unused,再drop unused columns,字段set之后就查不到了,中断后,表可正常使用;
  3. 先set unused,再drop unused columns checkpoint,中断后,insert和select均报ORA-12986错误,提示必须执行alter table drop columns continue操作,其他操作不允许。

测试总结:

  1. 在生产环境执行drop column是很危险的,如果是重要的或数据量很大的表,最好申请计划停机时间窗口进行维护。
  2. drop unused columns checkpoint虽然能解决回滚段占用过高的问题,但是会带来不可回退的风险。如果是非常大的表,只能让他跑完,但在跑的过程中,所有操作无法进行,这将会造成非常长时间的业务中断。
  3. 业务压力不大的系统可采用dbms_redefinition在线重定义操作,只会在finish那一步出现很短时间的阻塞。
  4. 间隔分区上执行drop unused columns checkpoint存在bug,一旦触发,同样会带来非常大的停机风险。

推荐阅读:144页!全是精华!分享珍藏已久的数据库技术年刊

相关推荐

【推荐】一个开源免费、AI 驱动的智能数据管理系统,支持多数据库

如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!.前言在当今数据驱动的时代,高效、智能地管理数据已成为企业和个人不可或缺的能力。为了满足这一需求,我们推出了这款开...

Pure Storage推出统一数据管理云平台及新闪存阵列

PureStorage公司今日推出企业数据云(EnterpriseDataCloud),称其为组织在混合环境中存储、管理和使用数据方式的全面架构升级。该公司表示,EDC使组织能够在本地、云端和混...

对Java学习的10条建议(对java课程的建议)

不少Java的初学者一开始都是信心满满准备迎接挑战,但是经过一段时间的学习之后,多少都会碰到各种挫败,以下北风网就总结一些对于初学者非常有用的建议,希望能够给他们解决现实中的问题。Java编程的准备:...

SQLShift 重大更新:Oracle→PostgreSQL 存储过程转换功能上线!

官网:https://sqlshift.cn/6月,SQLShift迎来重大版本更新!作为国内首个支持Oracle->OceanBase存储过程智能转换的工具,SQLShift在过去一...

JDK21有没有什么稳定、简单又强势的特性?

佳未阿里云开发者2025年03月05日08:30浙江阿里妹导读这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。阅前声明:本文介绍的内容基于AJDK21.0.5[1]以及以上...

「松勤软件测试」网站总出现404 bug?总结8个原因,不信解决不了

在进行网站测试的时候,有没有碰到过网站崩溃,打不开,出现404错误等各种现象,如果你碰到了,那么恭喜你,你的网站出问题了,是什么原因导致网站出问题呢,根据松勤软件测试的总结如下:01数据库中的表空间不...

Java面试题及答案最全总结(2025版)

大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...

数据库日常运维工作内容(数据库日常运维 工作内容)

#数据库日常运维工作包括哪些内容?#数据库日常运维工作是一个涵盖多个层面的综合性任务,以下是详细的分类和内容说明:一、数据库运维核心工作监控与告警性能监控:实时监控CPU、内存、I/O、连接数、锁等待...

分布式之系统底层原理(上)(底层分布式技术)

作者:allanpan,腾讯IEG高级后台工程师导言分布式事务是分布式系统必不可少的组成部分,基本上只要实现一个分布式系统就逃不开对分布式事务的支持。本文从分布式事务这个概念切入,尝试对分布式事务...

oracle 死锁了怎么办?kill 进程 直接上干货

1、查看死锁是否存在selectusername,lockwait,status,machine,programfromv$sessionwheresidin(selectsession...

SpringBoot 各种分页查询方式详解(全网最全)

一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...

《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略

《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...

LoadRunner(loadrunner录制不到脚本)

一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...

Redis数据类型介绍(redis 数据类型)

介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...

RMAN备份监控及优化总结(rman备份原理)

今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...

取消回复欢迎 发表评论: