db2look을 사용하여 데이터베이스를 모방합니까?
On 2월 14, 2021 by admin일부 데이터베이스를 iso8859-1에서 utf-8로 마이그레이션하는 중입니다. 데이터베이스 중 하나에는 1000 개 이상의 테이블, 많은 절차, 함수, 트리거, 제약 등.이 작업이 여러 번 발생하고 시스템의 여러 인스턴스에 대해 가능한 한 프로세스를 자동화하고 싶습니다. 이상적으로는 제 친구 Jenkins와 Ansible에게 작업을 넘겨주고 싶습니다. 😉
내 계획은 db2look을 사용하여 ddl을 생성하는 것이었지만 올바른 순서로 “객체”를 생성하지 못했습니다. -ct 플래그를 사용하거나 사용하지 않고 모두 실행하려고 시도했습니다 (다른 이유로 실패). . 예 :
connect to <db>; create table t1 (x int not null); create unique index t1pk on t1 (x); alter table t1 add constraint t1pk primary key (x); connect reset;
실행 중
db2look -d <db> -e -td @ -ct
인덱스에 대해 잘못된 순서를 생성합니다.
CREATE TABLE "DB2INST1"."T1" ( "X" INTEGER NOT NULL ) IN "USERSPACE1" ORGANIZE BY ROW@ ALTER TABLE "DB2INST1"."T1" ADD CONSTRAINT "T1PK" PRIMARY KEY ("X")@ CREATE UNIQUE INDEX "DB2INST1"."T1PK" ON "DB2INST1"."T1" ("X" ASC) COMPRESS NO INCLUDE NULL KEYS ALLOW REVERSE SCANS@
-ct 제거는이 간단한 예제에서 작동하지만 다른 종속성으로 인해 실제 데이터베이스에서는 실패합니다.
UTF-8로 마이그레이션하는 것이 매우 일반적인 작업이라고 생각합니다. 그래서 저는 어떤 p에 대해 궁금합니다. 사람들은 해냈습니다. 내가 볼 수있는 두 가지 해결책은 다음과 같습니다.
a) write a parser that inspects the catalog for database objects and sort them topologically using dependency tables. b) write a parser that reads the output from db2look, identify each object and sort them topologically using dependency tables.
이 두 가지 모두에 분명히 단점이 있습니다. 데이터베이스를 마이그레이션하는 사소한 방법을 간과하고 있습니까?
p>
편집 : 추가 관찰은 고유 / 기본 키 제약 조건을 통해 암시 적으로 생성 된 인덱스와 비교하여 인덱스에 추가 속성이 포함되지 않는 한 QL0605W
경고입니다. 제기됩니다. 반면에 추가 속성이 지정되면 SQL0601N
오류가 발생합니다. 예 :
CREATE UNIQUE INDEX X1 ON T1 (C1, C2) COMPRESS NO INCLUDE NULL KEYS DISALLOW REVERSE SCANS
기본 키 구문을 통해 유사한 색인이 생성 된 경우 경고 SQL0605W
를 생성합니다.
반면에 다음과 같은 색인은
CREATE UNIQUE INDEX X2 ON T2 (C1, C2) INCLUDE (C3) CLUSTER COMPRESS NO INCLUDE NULL KEYS ALLOW REVERSE SCANS
오류를 생성합니다. SQL0601N
. 나는 이것이 INCLUDE 절 때문이라고 생각하지만 아마도 CLUSTER 절이이 동작을 유발할 수도 있습니다.
Comments
답변
몇 년 전에 DB2를 9.7에서 10.5로 마이그레이션했습니다. 또한 데이터베이스를 새 하드웨어로 이동하고 데이터 압축을 구현했습니다. 이 때문에 우리는 처음부터 데이터베이스를 만들고 데이터를 내보내고 가져 오기로 결정했습니다.
우리는 db2look과 db2move를 사용하여 작업을 수행했습니다. 그러나 db2look에 의해 작성된 DDL을 올바른 순서로 가져올 수있는 방법이 없습니다. 테이블 생성, 트리거 생성, 인덱스 생성 등을 위해 생성 된 스크립트를 여러 부분으로 분할해야했습니다.
마지막으로 다음 단계로 끝납니다.
- export the 기존 데이터
- 새 데이터베이스 생성
- 버퍼 풀 및 테이블 스페이스 생성
- 테이블 생성
- 기본 키 생성
- 인덱스 생성
- 뷰 생성
- 데이터로드
- reorg 및 runstats 실행
- 저장 프로 시저, 사용자 정의 함수 및 트리거 생성
원하는 답변이 아니더라도 도움이되기를 바랍니다.
댓글
- 답변 해 주셔서 감사합니다. 상황은 좀 더 복잡합니다 (예를 들어 함수에 종속 된 테이블이 있고 그 반대의 경우도 있음). 저는 ‘ 종종 테이블을 사용하여 db2look의 출력을 토폴로지 순서로 정렬하는 파서를 만들 것입니다.
Answer
데이터베이스 개체를 올바른 순서로 가져 오는 방법에 대한 대략적인 아이디어. 종속성 그래프가 완전하지는 않지만 내 요구를 충족하는 것 같습니다.
#!/usr/bin/python3 import ibm_db import ibm_db_dbi from toposort import toposort, toposort_flatten cfg = ... conn = ibm_db.connect("DATABASE=%s;HOSTNAME=%s;PORT=50000;PROTOCOL=TCPIP;UID=%s; PWD=%s" % cfg,"","") find_edges = """ select * from ( SELECT "CONSTRAINT" as type, CONSTNAME, TABSCHEMA, TABNAME, BTYPE, "N/A", BSCHEMA, BNAME FROM SYSCAT.CONSTDEP WHERE TABSCHEMA NOT LIKE "SYS%" AND BSCHEMA NOT LIKE "SYS%" UNION ALL SELECT "I", "N/A", D.INDSCHEMA, D.INDNAME, D.BTYPE, "N/A", D.BSCHEMA, D.BNAME FROM SYSCAT.INDEXDEP D JOIN SYSCAT.INDEXES I ON D.INDSCHEMA = I.INDSCHEMA AND D.INDNAME = I.INDNAME WHERE I.TABSCHEMA NOT LIKE "SYS%" UNION ALL SELECT "I", "N/A", I.INDSCHEMA, I.INDNAME, "T", "N/A", I.TABSCHEMA, I.TABNAME FROM SYSCAT.INDEXES I WHERE I.TABSCHEMA NOT LIKE "SYS%" UNION ALL SELECT "F", "N/A", R1.ROUTINESCHEMA, R1.ROUTINENAME, D.BTYPE, "N/A" , COALESCE(R2.ROUTINESCHEMA, D.BSCHEMA), COALESCE(R2.ROUTINENAME, D.BNAME) FROM SYSCAT.ROUTINEDEP D JOIN SYSCAT.ROUTINES R1 ON D.ROUTINESCHEMA = R1.ROUTINESCHEMA AND D.SPECIFICNAME = R1.SPECIFICNAME LEFT JOIN SYSCAT.ROUTINES R2 ON D.BSCHEMA = R2.ROUTINESCHEMA AND D.BNAME = R2.SPECIFICNAME AND D.BTYPE = "F" WHERE D.ROUTINESCHEMA NOT LIKE "SYS%" AND D.BSCHEMA NOT LIKE "SYS%" AND D.BTYPE <> "K" UNION ALL SELECT "T", "N/A", TABSCHEMA, TABNAME, BTYPE, "N/A", BSCHEMA, BNAME FROM SYSCAT.TABDEP WHERE TABSCHEMA NOT LIKE "SYS%" AND BSCHEMA NOT LIKE "SYS%" UNION ALL SELECT "X", "N/A", TRIGSCHEMA, TRIGNAME, BTYPE, "N/A", BSCHEMA, BNAME FROM SYSCAT.TRIGDEP WHERE TRIGSCHEMA NOT LIKE "SYS%" AND BSCHEMA NOT LIKE "SYS%" UNION ALL SELECT "T", "N/A", TABSCHEMA, TABNAME, "T", "N/A", REFTABSCHEMA, REFTABNAME FROM SYSCAT.REFERENCES WHERE TABSCHEMA NOT LIKE "SYS%" ORDER BY 3,4 ) """ sedges = ibm_db.prepare(conn, find_edges) edges = {} ibm_db.execute(sedges, ()) lastnode = None tpl = ibm_db.fetch_tuple(sedges) while tpl: n1 = (tpl[0], tpl[1], tpl[2], tpl[3]) n2 = (tpl[4], tpl[5], tpl[6], tpl[7]) if lastnode == n1: edges[n1].add(n2) else: # print("new") edges[n1] = set() edges[n1].add(n2) lastnode = n1 tpl = ibm_db.fetch_tuple(sedges) x = list(toposort_flatten(edges))
이제 x를 사용하여 db2look에서 올바른 순서로 항목을 선택할 수 있습니다. db2look
의 출력을 목록으로 읽는 간단한 파서를 사용했습니다. x를 반복하고 올바른 버킷에서 정의를 선택하면 정렬 된 출력을 얻을 수 있습니다. 파서 자체는 정규 표현식의 무리이며 특별히 흥미롭지는 않지만 문이 여러 줄에 걸쳐 있기 때문에 stmt 판독기가 있으면 좋습니다.
# helper for reading stmt by stmt def myreadlines(f, newline): buf = "" while True: while newline in buf: pos = buf.index(newline) yield buf[:pos] buf = buf[pos + len(newline):] chunk = f.read(4096) if not chunk: yield buf break buf += chunk
편집 : https://github.com/lelle1234/Db2Utils 에 파서가 있습니다. 결코 완전하지는 않지만 내 필요에 맞았습니다.
주어진 쿼리와 데이터베이스에 대한 최적의 인덱스 세트를 찾는 인덱스 어드바이저도 있습니다.
답변
저는 다음 접근 방식을 사용하여 프로덕션 스키마를 개발자 용 테스트 서버에 복사했습니다. 트릭은 개별 실행 중 오류를 무시하고 마지막에 스키마를 비교하여 모든 것이 올바르게 다시 생성되는지 확인하는 것입니다. 나는 그것이 깨끗한 접근법이 아니라는 것을 압니다. 1,000 개가 넘는 테이블, 종속성, 제약 조건 등이있는 500 개의 함수가있는 스키마에 대해이 작업을 수행했습니다. 셸 스크립트를 사용하여 단계를 자동화 할 수 있습니다. 파서를 작성하고 테스트하는 것보다 훨씬 적은 노력이 필요합니다.
1 단계 스크립트를 사용하여 프로덕션 서버에서 특정 순서로 스키마를 추출합니다 (먼저 테이블 스페이스의 경우 db2look, 다음 테이블의 경우 db2look 등). 특정 순서를 사용하면 2 단계의 반복 횟수가 줄어 듭니다. & 3입니다.
2 단계 테스트 서버에서 1 단계의 출력 실행
3 단계 테스트 서버에서 스키마를 추출하고 프로덕션 서버의 스키마와 비교합니다.
4 단계 두 스키마가 동기화 될 때까지 2 단계와 3 단계를 반복합니다.
AUTO_REVAL
데이터베이스 구성 매개 변수를 설정합니까?DEFERRED_FORCE
문제를 해결 하시겠습니까?db2 +c -s ...
).