Vous utilisez db2look pour imiter une base de données?
On février 14, 2021 by adminJe suis en train de migrer certaines bases de données de iso8859-1 vers utf-8. Lune des bases de données contient plus de 1000 tables, des tas de procédures, fonctions, déclencheurs, contraintes etc. Je voudrais automatiser le processus autant que possible car cela va se produire plusieurs fois, et pour plusieurs instances du système. Idéalement, je voudrais confier le travail à mes amis Jenkins et Ansible 😉
Mon plan était de générer le ddl avec db2look, mais il ne parvient pas à générer les « objets » dans le bon ordre. Jai essayé dexécuter à la fois avec et sans loption -ct (échoue pour différentes raisons) . Par exemple:
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;
Lexécution
db2look -d <db> -e -td @ -ct
génère le mauvais ordre pour lindex et la contrainte.
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@
La suppression de -ct fonctionne dans cet exemple trivial, mais échoue dans la base de données réelle en raison dautres dépendances.
Jimagine que la migration vers UTF-8 est une tâche assez courante donc je suis curieux de savoir ce que p les gens lont fait. Les deux solutions possibles que je vois sont les suivantes:
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.
De toute évidence, il y a des inconvénients avec les deux, est-ce que je néglige un moyen trivial de migrer les bases de données?
EDIT: Une observation supplémentaire est que tant quun index ne contient pas dattributs supplémentaires par rapport à lindex créé implicitement via une contrainte de clé unique / primaire, un avertissement QL0605W
est soulevé. Si en revanche des attributs supplémentaires sont spécifiés, une erreur SQL0601N
est générée. Exemple:
CREATE UNIQUE INDEX X1 ON T1 (C1, C2) COMPRESS NO INCLUDE NULL KEYS DISALLOW REVERSE SCANS
génère un avertissement SQL0605W
si un index similaire est créé via une instruction de clé primaire.
Par contre un index comme:
CREATE UNIQUE INDEX X2 ON T2 (C1, C2) INCLUDE (C3) CLUSTER COMPRESS NO INCLUDE NULL KEYS ALLOW REVERSE SCANS
génère une erreur SQL0601N
. Je suppose que cela est dû à la clause INCLUDE, mais peut-être que la clause CLUSTER provoquera également ce comportement.
Commentaires
Réponse
Il y a quelques années, nous avons migré notre DB2 de 9.7 vers 10.5. Nous avons également déplacé la base de données vers un nouveau matériel et mis en œuvre la compression des données. Pour cette raison, nous avons décidé de créer la base de données à partir de zéro et dexporter et dimporter les données.
Nous avons utilisé db2look et db2move pour faire le travail. Cependant, il ny avait aucun moyen dobtenir le DDL créé par db2look dans le bon ordre. Nous avons dû diviser le script généré en différentes parties pour créer des tables, créer des triggers, créer des index, etc.
Enfin nous nous retrouvons avec les étapes suivantes:
- exporter le données existantes
- créer la nouvelle base de données
- créer des pools de mémoire tampon et des tablespaces
- créer des tables
- créer des clés primaires
- créer des index
- créer des vues
- charger des données
- exécuter des réorganisations et des runstats
- créer des procédures stockées, des fonctions définies par lutilisateur et des déclencheurs
Jespère que cela aide, même si ce nest pas la réponse à laquelle vous vous attendiez.
Commentaires
- Merci pour votre réponse. La situation est un peu plus compliquée (il existe par exemple des tables dépendantes des fonctions et vice versa). Je ‘ Je vais probablement créer un analyseur qui trie la sortie de db2look dans lordre topologique à laide de tables de dépendances.
Réponse
Idée approximative sur la façon dobtenir des objets de base de données dans le bon ordre. Le graphe de dépendances nest pas complet mais semble répondre à mes besoins.
#!/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))
Maintenant, x peut être utilisé pour choisir les choses dans le bon ordre dans db2look. Jai utilisé un analyseur trivial qui lit la sortie de db2look
dans des listes. En bouclant sur x et en choisissant la définition dans le bon compartiment, une sortie triée peut être obtenue. Lanalyseur lui-même nest quun tas dexpressions régulières et pas particulièrement intéressant, mais comme les instructions sont réparties sur plusieurs lignes, un lecteur stmt est bien davoir:
# 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
EDIT: Jai un analyseur à https://github.com/lelle1234/Db2Utils . Il nest en aucun cas complet mais a fonctionné pour mes besoins.
Il y a aussi un conseiller dindex qui essaie de trouver un ensemble optimal dindex pour une requête donnée et une base de données.
Réponse
Jai utilisé lapproche suivante pour copier le schéma de production pour tester les serveurs pour les développeurs. Lastuce consiste à ignorer les erreurs lors des exécutions individuelles et à comparer le schéma à la fin pour vous assurer que tout est recréé correctement. Je sais que ce nest pas une approche claire. Jai fait ceci contre le schéma avec plus de 1000 tables, 500 fonctions avec des dépendances, des contraintes, etc. Vous pouvez automatiser les étapes en utilisant le script shell. Cela demande beaucoup moins deffort que décrire un analyseur et de le tester.
Étape 1 Utilisez un script pour extraire le schéma du serveur de production dans un ordre spécifique (db2look pour les tablespaces en premier, db2look pour les tables ensuite, etc.). Lutilisation dun ordre spécifique réduit le nombre ditérations pour létape 2 & 3.
Étape 2 Exécutez la sortie de létape 1 sur le serveur de test
Étape 3 Extrayez le schéma du serveur de test et comparez-le avec le schéma du serveur de production
Étape 4 Répétez les étapes 2 et 3, jusquà ce que les deux schémas soient synchronisés.
AUTO_REVAL
DEFERRED_FORCE
résoudre votre problème?db2 +c -s ...
) pour pouvoir dire en toute sécurité que tout est recréé correctement.