Tietokannan jäljittelemiseen käytetään db2lookia?
On helmikuu 14, 2021 by adminOlen siirtämässä joitain tietokantoja iso8859-1: stä utf-8: een. Yksi tietokannoista sisältää yli 1000 taulukkoa, paljon menettelyjä, Toiminnot, laukaisimet, rajoitukset jne. Haluan automatisoida prosessin niin paljon kuin mahdollista, koska sitä tapahtuu useita kertoja ja useille järjestelmän esiintymille. Ihannetapauksessa haluaisin luovuttaa työn ystävilleni Jenkins ja Ansible 😉
Suunnitelmani oli luoda ddl db2lookilla, mutta se ei onnistunut luomaan ”objekteja” oikeassa järjestyksessä. Yritin suorittaa sekä -ct-lipun kanssa että ilman sitä (epäonnistuu eri syistä) Esimerkki:
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;
käynnissä
db2look -d <db> -e -td @ -ct
tuottaa hakemistolle väärän järjestyksen ja rajoitus.
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: n poistaminen toimii tässä triviaalissa esimerkissä, mutta epäonnistuu todellisessa tietokannassa muiden riippuvuuksien vuoksi.
Kuvittelen, että siirtyminen UTF-8: een on melko yleinen tehtävä, joten olen utelias mitä s ihmiset ovat tehneet. Kaksi näkemääni ratkaisua ovat:
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.
Näiden molempien kanssa on selvästikin haittoja, unohdanko jotakin triviaalia tapaa siirtää tietokantoja?
MUOKKAA: Lisähavainto on, että niin kauan kuin hakemisto ei sisällä ylimääräisiä määritteitä verrattuna implisiittisesti luotuun hakemistoon yksilöllisen / ensisijaisen avaimen rajoituksen kautta, QL0605W
-varoitus on nostettu. Jos toisaalta määritetään muita määritteitä, SQL0601N
-virhe nousee. Esimerkki:
CREATE UNIQUE INDEX X1 ON T1 (C1, C2) COMPRESS NO INCLUDE NULL KEYS DISALLOW REVERSE SCANS
luo varoituksen SQL0605W
, jos samanlainen hakemisto luodaan ensisijaisen avaimen käskyllä.
Toisaalta hakemisto, kuten:
CREATE UNIQUE INDEX X2 ON T2 (C1, C2) INCLUDE (C3) CLUSTER COMPRESS NO INCLUDE NULL KEYS ALLOW REVERSE SCANS
tuottaa virheen SQL0601N
. Oletan, että tämä johtuu INCLUDE-lauseesta, mutta ehkä CLUSTER-lauseke aiheuttaa myös tämän käyttäytymisen.
Kommentit
Vastaus
Muutama vuosi sitten siirrimme DB2: n 9.7: stä 10.5: een. Siirtimme myös tietokannan uuteen laitteistoon ja otimme käyttöön tietojen pakkaamisen. Tämän vuoksi päätimme luoda tietokannan tyhjästä ja viedä ja tuoda tiedot.
Käytimme db2lookia ja db2move tehtävän suorittamiseen. Ei ollut kuitenkaan mitään keinoa saada db2lookin luomaa DDL: ää oikeassa järjestyksessä. Meidän oli jaettava luotu komentosarja eri osiin taulukkojen luomiseksi, laukaisimien luomiseksi, hakemistojen luomiseksi jne.
Lopuksi suoritetaan seuraavat vaiheet:
- viedä olemassa olevat tiedot
- luo uusi tietokanta
- luo puskurialueita ja taulukotiloja
- luo taulukoita
- luo ensisijaiset avaimet
- luo hakemistoja
- luo näkymiä
- lataa tietoja
- ajaa uudelleenorganisointeja ja runstatteja
- luo tallennettuja toimintoja, käyttäjän määrittelemiä toimintoja ja laukaisimia
Toivon, että se auttaa, vaikka se ei olisikaan vastausta, jota olet ehkä odottanut.
kommentit
- Kiitos vastauksestasi. Tilanne on hiukan monimutkaisempi (on esimerkiksi taulukoita, jotka ovat riippuvaisia toiminnoista ja päinvastoin). ’ Luon todennäköisesti jäsentimen, joka lajittelee lähdön db2lookista topologisessa järjestyksessä riippuvuustaulukoiden avulla.
Vastaa
Karkea idea siitä, miten tietokantaobjektit saadaan oikeaan järjestykseen. Riippuvuuskaavio ei ole täydellinen, mutta se näyttää täyttävän tarpeeni.
#!/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))
Nyt x: llä voidaan valita asioita oikeassa järjestyksessä db2lookista. Käytin triviaalia jäsennintä, joka lukee db2look
-lähdön luetteloiksi. Lajittelemalla ulostulo voidaan saavuttaa silmukka x: n yli ja valita määritelmä oikeasta ämpäriin. Jäsennys itsessään on vain joukko säännöllisiä lausekkeita eikä ole erityisen mielenkiintoinen, mutta koska lausekkeet on jaettu usealle riville, STMT-lukijalla on mukava olla:
# 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
MUOKKAA: Minulla on jäsennin yläosassa https://github.com/lelle1234/Db2Utils . Se ei ole suinkaan täydellinen, mutta toimi minun tarpeitani.
Siellä on myös hakemistoneuvoja, joka yrittää luoda optimaalisen indeksisarjan tietylle kyselylle ja tietokannalle.
vastaus
Olen käyttänyt seuraavaa lähestymistapaa tuotantomallin kopioimiseen kehittäjien palvelimille. Temppu on jättää huomiotta virheet yksittäisissä ajoissa ja verrata kaavaa lopussa varmistaaksesi, että kaikki on luotu oikein. Tiedän, että se ei ole puhdas lähestymistapa. Olen tehnyt tämän vastaan skeemaa, jossa on yli 1000 taulukkoa, 500 funktiota riippuvuuksilla, rajoituksilla jne. Voit automatisoida vaiheet käyttämällä komentosarjaa. Se vaatii paljon vähemmän vaivaa kuin jäsennin kirjoittaminen ja testaaminen.
Vaihe 1 Käytä komentosarjaa poimimalla skeema tuotantopalvelimelta tietyssä järjestyksessä (db2look ensin taulukotiloille, db2look seuraaville taulukoille jne.). Tietyn järjestyksen käyttäminen vähentää vaiheen 2 iteraatioiden määrää & 3.
Vaihe 2 Suorita lähtö palvelimen vaiheesta 1
Vaihe 3 Pura skeema testipalvelimelta ja vertaa sitä tuotantopalvelimen skeemaan.
Vaihe 4 Toista vaiheet 2 ja 3, kunnes molemmat mallit ovat synkronoituja.
AUTO_REVAL
tietokannan kokoonpanoparametriDEFERRED_FORCE
ratkaista ongelmasi?db2 +c -s ...
), jotta voin turvallisesti sanoa, että kaikki on luotu uudelleen oikein.