Oracle数据表默认值列添加与行迁移(Row Migration)
在笔者之前的文章中,已经探讨过给一个数据表添加有默认值列是一项非常危险的事情,特别是在在线生产环境下。给一张大数据表添加有默认值列,最直接的有下面几个严重危害: 系统高负荷运行,消耗大量资源。添加列操作是一次性的DDL操作,生成大量的Redo Log记
在笔者之前的文章中,已经探讨过给一个数据表添加有默认值列是一项非常“危险”的事情,特别是在在线生产环境下。给一张大数据表添加有默认值列,最直接的有下面几个严重危害:系统高负荷运行,消耗大量资源。添加列操作是一次性的DDL操作,生成大量的Redo Log记录;
长期数据表锁定,阻碍生产系统作业。添加数据列期间,对数据表添加独占锁,此时阻碍其他DML操作;
破坏原有存储结构,造成大量的行迁移(Row Migration)数据。在每个数据行尝试添加进默认值,进行膨胀的同时,由于rowid的特性,会引起严重的行链接情况,损害原有数据表存储结构;
本文主要想聊聊由于默认值添加带来的行链接(Row Migration)现象。
1、从Row Migration现象谈起
Row Migration本质上是一种由于Oracle存储特性和数据行定位特性而发生的一种现象。在Oracle中,所有的数据行都是保留在数据块单元上的。一个数据块可以容纳若干条数据(通常条件下)。一些数据列,如varchar2类型,大部分情况下都是根据输入数据的长度进行空间分配。
那么,如果数据行列填入了更大的数据,也就是空间发生了拓展。数据块存储上就会发生何种变化呢?每个数据块都会预留一部分的空闲空间,作为数据行变化预留位置。如果长度继续拓展,那么会发生什么呢?
Oracle会尝试将这个数据行拷贝出,找个新的数据块进行存储。这样,就可以放下数据块。那么,一个新的问题出现了,就是Rowid问题。
在Oracle中,Rowid是定位一条记录的物理地址。Rowid包括数据文件相对编号、对象号、数据块号和Slot行号。Rowid普遍作为数据行的标记,保存在相关的索引叶子节点上。但是,当一个数据行被转移存储到另一个数据块,本质上物理存储位置已经发生变化。索引等对象中包括的Rowid面临着失效的问题。
Oracle解决这个问题是通过“虚拟门牌”的方法。这个数据行位置虽然已经到另外的地方,但是对应的Rowid并没有发生变化。当我们检索数据,Server Process定位到原来的位置时,它会找到一个转换跳转地址,那里面记录着真正的Rowid地址。这个就是发生了Row Migration。
Row Migration给系统性能带来了很多潜在的问题。比如,一行数据原来只需要寻找一个数据块记录,现在就需要寻找多个数据块才可以。这样就是带来的性能问题。
我们在进行默认值数据行添加的时候,就会带来Row Migration的爆发。
2、Row Migration与默认值列添加
下面我们通过实验,来证明Row Migration的出现。我们选择11gR2环境进行实验。
SQL> select * from v$version;
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
SQL> create table t as select object_id from dba_objects where 1=0;
Table created
--添加若干条记录;
SQL> insert into t select object_id from dba_objects where rownum
99 rows inserted
SQL> commit;
Commit complete
数据表T,在存储结构和空间分配上情况如下:
SQL> exec dbms_stats.gather_table_stats(user,'T',cascade => true);
PL/SQL procedure successfully completed
SQL> select bytes, blocks,extents from user_segments where segment_name='T';
BYTES BLOCKS EXTENTS
---------- ---------- ----------
65536 8 1
SQL> select blocks from user_tables where table_name='T';
BLOCKS
----------
1
User_segment中记录着给数据段分配的总空间,但这并不代表全部的HWM位置。User_tables中的blocks,才代表HWM下数据块的个数。从上面的结果看,HWM下一共只有一个数据块。从rowid分析看,实际也的确如此。
SQL> select dbms_rowid.rowid_block_number(rowid) blockno, count(*) from t group by dbms_rowid.rowid_block_number(rowid);
BLOCKNO COUNT(*)
---------- ----------
85857 99
下面我们进行数据列添加。
SQL> alter table t add vc varchar2(1000) default lpad('T',500,'T');
Table altered
Executed in 0.078 seconds
对应的空间使用情况如下:
SQL> exec dbms_stats.gather_table_stats(user,'T',cascade => true);
PL/SQL procedure successfully completed
Executed in 0.141 seconds
SQL> select blocks from user_tables where table_name='T';
BLOCKS
----------
12
Executed in 0.016 seconds
SQL> select bytes, blocks,extents from user_segments where segment_name='T';
BYTES BLOCKS EXTENTS
---------- ---------- ----------
131072 16 2
SQL> select dbms_rowid.rowid_block_number(rowid) blockno, count(*) from t group by dbms_rowid.rowid_block_number(rowid);
BLOCKNO COUNT(*)
---------- ----------
85857 99
Executed in 0.016 seconds
上面的情况可以看出,Oracle的数据表T已经推高了水位线HWM到12个块,从空间分配也分配了新的extent使用。
但是,所有数据行rowid没有变化。所有数据行的“门牌号”都没有变化,但是存储呢?很诡异的增加了。正常容量下,数据块情况应该是如下:
SQL> create table t_bak as select * from t;
Table created
SQL> exec dbms_stats.gather_table_stats(user,'T_BAK',cascade => true);
PL/SQL procedure successfully completed
SQL> select bytes, blocks,extents from user_segments where segment_name='T_BAK';
BYTES BLOCKS EXTENTS
---------- ---------- ----------
131072 16 2
SQL> select blocks from user_tables where table_name='T_BAK';
BLOCKS
----------
8
SQL> select dbms_rowid.rowid_block_number(rowid) blockno, count(*) from t_bak group by dbms_rowid.rowid_block_number(rowid);
BLOCKNO COUNT(*)
---------- ----------
86589 14
86588 14
86585 14
86586 14
86591 14
86590 14
86587 14
86592 1
8 rows selected
下面,我们来证明发生了行链接情况。
3、数据表行链接检验
Analyze语句一度是非常流行的收集数据表统计量的操作方式。但是随着dbms_stats包的成熟推广,analyze在统计量收集方面的功能已经渐渐弱化。但是,Oracle依然保留了这个语句的两个基本功能:对数据表进行行链接(Row Migration)检测和索引健康程度检测。
下面使用analyze语句进行数据表T的检测。首先我们需要创建分析结果的容纳数据表。
--调用Oracle_HOME下的脚本;
SQL>@?/rdbms/admin/utlchain.sql
Table created.
SQL> desc chained_rows;
Name Null? Type
----------------------------------------- -------- ----------------------------
OWNER_NAME VARCHAR2(30)
TABLE_NAME VARCHAR2(30)
CLUSTER_NAME VARCHAR2(30)
PARTITION_NAME VARCHAR2(30)
SUBPARTITION_NAME VARCHAR2(30)
HEAD_ROWID ROWID
ANALYZE_TIMESTAMP DATE
SQL> create public synonym chained_rows for chained_rows;
Synonym created.
SQL> grant all on chained_rows to public;
Grant succeeded.
分析数据表,如下:
--检验数据行Row Migration情况;
SQL> analyze table t list chained rows into chained_rows;
Table analyzed
Executed in 0.125 seconds
--发生Row Migration次数;
SQL> select count(*) from chained_rows;
COUNT(*)
----------
86
Executed in 0.016 seconds
SQL> select head_rowid from chained_rows where rownum
HEAD_ROWID
------------------
AAASUCAABAAAU9hAAN
AAASUCAABAAAU9hAAO
AAASUCAABAAAU9hAAP
AAASUCAABAAAU9hAAQ
Executed in 0.016 seconds
SQL> select * from t where rowid='AAASUCAABAAAU9hAAQ';
OBJECT_ID VC
---------- --------------------------------------------------------------------------------
38 TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
Executed in 0.016 seconds
在99行记录中,发生了86次行链接Row Migration情况。
4、结论
解决Oracle Row Migration的方法,就是进行数据表重构,重新对存储结构和Rowid进行整理。我们说,在生产环境下,进行有默认值数据列的添加操作,会引起一系列的问题,要三思而行。

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

Oracle에 대한 솔루션은 개설 할 수 없습니다. 1. 데이터베이스 서비스 시작; 2. 청취자를 시작하십시오. 3. 포트 충돌을 확인하십시오. 4. 환경 변수를 올바르게 설정하십시오. 5. 방화벽이나 바이러스 백신 소프트웨어가 연결을 차단하지 않도록하십시오. 6. 서버가 닫혀 있는지 확인하십시오. 7. RMAN을 사용하여 손상된 파일을 복구하십시오. 8. TNS 서비스 이름이 올바른지 확인하십시오. 9. 네트워크 연결 확인; 10. Oracle 소프트웨어를 다시 설치하십시오.

Oracle Cursor Closure 문제를 해결하는 방법에는 다음이 포함됩니다. Close 문을 사용하여 커서를 명시 적으로 닫습니다. For Update 절에서 커서를 선언하여 범위가 종료 된 후 자동으로 닫히십시오. 연관된 PL/SQL 변수가 닫히면 자동으로 닫히도록 사용 절에서 커서를 선언하십시오. 예외 처리를 사용하여 예외 상황에서 커서가 닫혀 있는지 확인하십시오. 연결 풀을 사용하여 커서를 자동으로 닫습니다. 자동 제출을 비활성화하고 커서 닫기를 지연시킵니다.

Oracle에서 FOR 루프 루프는 커서를 동적으로 생성 할 수 있습니다. 단계는 다음과 같습니다. 1. 커서 유형을 정의합니다. 2. 루프를 만듭니다. 3. 커서를 동적으로 만듭니다. 4. 커서를 실행하십시오. 5. 커서를 닫습니다. 예 : 커서는 상위 10 명의 직원의 이름과 급여를 표시하기 위해주기별로 만들 수 있습니다.

Oracle Log 파일이 가득 차면 다음 솔루션을 채택 할 수 있습니다. 1) 오래된 로그 파일 청소; 2) 로그 파일 크기를 늘리십시오. 3) 로그 파일 그룹을 늘리십시오. 4) 자동 로그 관리를 설정합니다. 5) 데이터베이스를 다시 이용하십시오. 솔루션을 구현하기 전에 데이터 손실을 방지하기 위해 데이터베이스를 백업하는 것이 좋습니다.

Centos 시스템에서 Hadoop 분산 파일 시스템 (HDF)을 구축하려면 여러 단계가 필요합니다. 이 기사는 간단한 구성 안내서를 제공합니다. 1. 초기 단계에서 JDK를 설치할 준비 : 모든 노드에 JavadevelopmentKit (JDK)을 설치하면 버전이 Hadoop과 호환되어야합니다. 설치 패키지는 Oracle 공식 웹 사이트에서 다운로드 할 수 있습니다. 환경 변수 구성 : /etc /프로파일 파일 편집, Java 및 Hadoop 설정 설정 시스템에서 JDK 및 Hadoop의 설치 경로를 찾을 수 있습니다. 2. 보안 구성 : SSH 비밀번호가없는 로그인 SSH 키 : 각 노드에서 ssh-keygen 명령을 사용하십시오.

Oracle은 데이터베이스 회사 일뿐 만 아니라 클라우드 컴퓨팅 및 ERP 시스템의 리더이기도합니다. 1. Oracle은 데이터베이스에서 클라우드 서비스 및 ERP 시스템에 이르기까지 포괄적 인 솔루션을 제공합니다. 2. OracleCloud는 AWS와 Azure에 도전하여 IAA, PAAS 및 SAAS 서비스를 제공합니다. 3. E-BusinessSuite 및 FusionApplications와 같은 Oracle의 ERP 시스템은 기업이 운영을 최적화하는 데 도움이됩니다.

Oracle 데이터베이스를 중지하려면 다음 단계를 수행하십시오. 1. 데이터베이스에 연결하십시오. 2. 즉시 종료; 3. 셧다운은 완전히 중단됩니다.

Oracle View는 Expitility : Oracle 데이터베이스에 로그인하여 내보낼 수 있습니다. 뷰 이름 및 내보내기 디렉토리를 지정하여 EXP 유틸리티를 시작하십시오. 대상 모드, 파일 형식 및 테이블 스페이스를 포함한 내보내기 매개 변수를 입력하십시오. 내보내기를 시작하십시오. IMPDP 유틸리티를 사용하여 내보내기를 확인하십시오.
