A db2look használata az adatbázis utánzásához?
On február 14, 2021 by adminI m az egyes adatbázisok iso8859-1-ről utf-8-ra történő áttelepítése során. Az egyik adatbázis több mint 1000 táblázatot tartalmaz, rengeteg eljárást, függvények, eseményindítók, korlátozások stb. Szeretném a lehető legjobban automatizálni a folyamatot, mivel ez többször és a rendszer több példányára is sor kerül. Ideális esetben a munkát át szeretném adni Jenkins és Ansible barátaimnak. 😉
Az volt a tervem, hogy a ddl-t db2look-tal állítsam elő, de nem sikerült az “objektumokat” megfelelő sorrendben előállítani. Megpróbáltam futtatni a -ct jelzővel és anélkül is (különböző okokból nem sikerül) Például:
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;
futó
db2look -d <db> -e -td @ -ct
hibás sorrendet generál az index számára és a megkötés.
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@
A -ct eltávolítása ebben a triviális példában működik, de az aktuális adatbázisban más függőségek miatt nem sikerül.
Úgy képzelem, hogy az UTF-8-ra való migráció meglehetősen gyakori feladat, ezért kíváncsi vagyok, mi a p az emberek megtették. A két lehetséges megoldást a következőknek látom:
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.
Mindkettővel egyértelműen vannak hátrányok, figyelmen kívül hagyok-e valamilyen triviális módot az adatbázisok áttelepítésére?
SZERKESZTÉS: További megfigyelés az, hogy amíg egy index nem tartalmaz semmilyen extra attribútumot az implicit módon létrehozott indexhez képest, az egyedi / elsődleges kulcs korlátozása révén QL0605W
figyelmeztetés emelkedett. Ha viszont további attribútumokat ad meg, akkor SQL0601N
hiba lép fel. Példa:
CREATE UNIQUE INDEX X1 ON T1 (C1, C2) COMPRESS NO INCLUDE NULL KEYS DISALLOW REVERSE SCANS
figyelmeztetést generál SQL0605W
, ha hasonló index jön létre az elsődleges kulcs utasítással.
Másrészt egy olyan index, mint:
CREATE UNIQUE INDEX X2 ON T2 (C1, C2) INCLUDE (C3) CLUSTER COMPRESS NO INCLUDE NULL KEYS ALLOW REVERSE SCANS
hibát generál SQL0601N
. Feltételezem, hogy ez az INCLUDE záradéknak köszönhető, de talán a CLUSTER záradék is ezt a viselkedést fogja okozni.
Megjegyzések
Válasz
Néhány évvel ezelőtt átállítottuk a DB2-t 9.7-ről 10.5-re. Az adatbázist új hardverre is áthelyeztük, és megvalósítottuk az adatok tömörítését. Emiatt úgy döntöttünk, hogy az adatbázist a semmiből hozzuk létre, majd exportáljuk és importáljuk az adatokat.
A db2look és a db2move használatával végeztük a munkát. Arra azonban nem volt mód, hogy a db2look által létrehozott DDL-t a megfelelő sorrendbe állítsuk. A létrehozott szkriptet különböző részekre kellett osztanunk táblák létrehozásához, triggerek létrehozásához, indexek létrehozásához stb.
Végül a következő lépéseket hajtjuk végre:
- exportálja a meglévő adatok
- új adatbázis létrehozása
- bufferpoolok és táblaterek létrehozása
- táblák létrehozása
- elsődleges kulcsok létrehozása
- indexek létrehozása
- nézetek létrehozása
- adatok betöltése
- reorgok és runstats futtatása
- tárolt eljárások, felhasználó által definiált függvények és triggerek létrehozása
Remélem, hogy segít, még ez sem a válasz, amire számíthattál.
Megjegyzések
- Köszönöm, hogy válaszoltál. A helyzet egy kicsit bonyolultabb (vannak például táblák, amelyek függenek a függvényektől és fordítva). ‘ Valószínűleg létrehozok egy elemzőt, amely a db2look kimenetét topológiai sorrendbe rendezi függőségi táblázatok segítségével.
Válasz
Durva ötlet arról, hogyan lehet az adatbázis-objektumokat a megfelelő sorrendbe állítani. A függőségi grafikon nem teljes, de úgy tűnik, hogy kielégíti az igényeimet.
#!/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))
Mostantól az x használható a dolgok helyes sorrendben történő kiválasztására a db2lookból. Olyan triviális elemzőt használtam, amely felolvassa a kimenetet a db2look
listákra. Az x hurokba kapcsolásával és a definíció kiválasztásával a jobb vödörből rendezett kimenet érhető el. Az elemző maga csak egy csomó reguláris kifejezés, és nem különösebben érdekes, de mivel az állítások több soron vannak elosztva, egy stmt olvasó örömmel rendelkezik:
# 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
SZERKESZTÉS: Van egy elemzőm a https://github.com/lelle1234/Db2Utils címen. Semmi esetre sem teljes, de az én igényeimnek megfelelően dolgozott.
Van egy index tanácsadó is, amely megpróbál optimális indexkészletet felmutatni egy adott lekérdezéshez és egy adatbázishoz.
Válasz
A következő megközelítést alkalmaztam a gyártási séma másolására a szerverek teszteléséhez a fejlesztők számára. A trükk az, hogy figyelmen kívül hagyja az egyes futtatások során elkövetett hibákat, és a végén összehasonlítja a sémát, hogy megbizonyosodjon arról, hogy minden rendben van-e. Tudom, hogy ez nem tiszta megközelítés. Ezt több mint 1000 táblával, 500 függvénnyel, korlátokkal stb. Rendelkező sémával szemben tettem meg. Automatizálhatja a lépéseket a shell parancsfájl segítségével. Sokkal kevesebb erőfeszítést igényel az értelmező írásához és teszteléséhez képest.
1. lépés Használja a parancsfájlt a séma kibontásához a termelési kiszolgálóról meghatározott sorrendben (először a db2look a táblaterületekhez, a következő táblákhoz stb.). Meghatározott sorrend használata csökkenti a 2. lépés iterációinak számát & 3.
2. lépés Futtassa a kimenetet az 1. lépéstől a tesztkiszolgálón. Bontsa ki a sémát a tesztkiszolgálóról, és hasonlítsa össze a termelési kiszolgáló sémájával.
4. lépés Ismételje meg a 2. és a 3. lépést, amíg mindkét séma szinkronban van.
AUTO_REVAL
adatbázis konfigurációs paramétertDEFERRED_FORCE
megoldani a problémáját?db2 +c -s ...
) való futást, hogy nyugodtan kijelenthessem, hogy mindent helyesen hoztak létre.