# comparedb **Repository Path**: hwrd/comparedb ## Basic Information - **Project Name**: comparedb - **Description**: 获取Oracle表的结构,计算表记录的md5值,打印为字符串,用于比较迁移后两个数据库的表和表内容是否相同。 可用于Oracle到Oracle数据库迁移,或Oracle与PG之间数据库迁移。 - **Primary Language**: Python - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-12-06 - **Last Updated**: 2023-04-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ``` 获取Oracle表的结构,计算表记录的md5值,打印为字符串,用于比较迁移后两个数据库的表和表内容是否相同。 可用于Oracle到Oracle数据库迁移,或Oracle与PG之间数据库迁移。 运行脚本的机器上需要安装有Python3和Oracle客户端库。 下载: https://www.oracle.com/cn/database/technologies/instant-client/linux-x86-64-downloads.html 安装: sudo rpm -ivh oracle-instantclient12.2-basic-12.2.0.1.0-1.x86_64.rpm sudo rpm -ivh oracle-instantclient12.2-devel-12.2.0.1.0-1.x86_64.rpm sudo rpm -ivh oracle-instantclient12.2-jdbc-12.2.0.1.0-1.x86_64.rpm sudo rpm -ivh oracle-instantclient12.2-sqlplus-12.2.0.1.0-1.x86_64.rpm 然后设置下面的环境变量: export ORACLE_HOME=/usr/lib/oracle/12.2/client64 export LD_LIBRARY_PATH=/usr/lib/oracle/12.2/client64/lib:$LD_LIBRARY_PATH export PATH=/usr/lib/oracle/12.2/client64/bin:$PATH export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK 环境变量也可以放到~/.bash_profile中。 在Python3安装cx_Oracle模块: pip install cx_Oracle 或者事先下载cx_Oracle的wheel文件,复制到目的机器再安装: pip download -d wheel cx_Oracle pip install cx_Oracle-8.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl 注意,在演练中发现,由于12c和19c元数据版本的不同,比较某个表的index和check约束时,个别表会打印不同内容,但是实际上是相同的,这种情况可以人工查明原因后处理。 使用说明 1)get_objects_from_ora.py 这个脚本连接Oracle数据库,查询数据字典,打印表的定义、索引、外键。 执行get_object_from_ora.py之前,需要打开文件修改连接Oracle的参数: ora_username是连接Oracle数据库的用户 ora_password是用户密码 ora_conn_str是Oracle连接字符串,格式:ip:port/sid 这个脚本有6个子命令,如下: Usage: get_objects_from_ora.py [OPTIONS] COMMAND [ARGS]... Options: --help Show this message and exit. Commands: check Get check constraint info of each table. fk Get foreign key defination of each table. index Get primary key, index and unique defination of each table. seq Get all sequence names tab Get all table names tabdef Get defination of each table. a)get_objects_from_ora.py check --打印一个或多个表的CHECK约束信息 选项-i指定一个文本文件,里面每一行是一个表名,注意指定表名时,不要指定schema或用户名前缀。 选项-l直接指定一个或多个表名列表,以逗号‘,’分隔。 下图的例子打印ACT_RE_PROCDEF表的CHECK约束,其中包含了非NULL约束。 b)get_objects_from_ora.py fk --打印一个或多个表的外键信息 例如, ./get_objects_from_ora.py fk -l ACT_RU_IDENTITYLINK 下面每一行表示一个外键的定义,ACT_RU_IDENTITYLINK表有三个外键 ACT_RU_IDENTITYLINK : PROC_DEF_ID_ -> ACT_RE_PROCDEF : ID_ ACT_RU_IDENTITYLINK : PROC_INST_ID_ -> ACT_RU_EXECUTION : ID_ ACT_RU_IDENTITYLINK : TASK_ID_ -> ACT_RU_TASK : ID_ 第一行,表示ACT_RU_IDENTITYLINK表的PROC_DEF_ID_列引用了ACT_RE_PROCDEF表的ID_列。 第二行,表示ACT_RU_IDENTITYLINK表的PROC_INST_ID_ 列引用了ACT_RU_EXECUTION表的ID_列。 第三行类似。 c)get_objects_from_ora.py index --打印一个或多个表的索引(包括主键)信息 参数含义和外键类似,例如, ./get_objects_from_ora.py index -lACT_RE_PROCDEF ACT_RE_PROCDEF : ID_ ACT_RE_PROCDEF : KEY_,VERSION_,TENANT_ID_ 每一行表示一个索引的定义,ACT_RE_PROCDEF表有两个索引,每个索引打印一行,第一个索引列为ID_,第二个索引由KEY_,VERSION_,TENANT_ID_列组成。 d)get_objects_from_ora.py seq --打印用户的所有序列名,即user_sequences数据字典里所有的序列名。这个子命令没有参数。 e)get_objects_from_ora.py tab--打印用户的所有表名,即user_tables里的所有表名。这个子命令没有参数。 f)get_objects_from_ora.py tabdef --打印一个或多个表的定义,即列名和列类型 参数-i和-l的含义与fk和index相同,例如, ./get_objects_from_ora.py tabdef -l"UV_TENANT_CODE,UV_TENANT_RESOURCE_INFO" UV_TENANT_CODE: TENANT_ID NUMBER 22 Y TENANT_CODE NUMBER 22 Y UV_TENANT_ID VARCHAR2 20 Y UV_BS_ID VARCHAR2 20 Y UV_TENANT_RESOURCE_INFO: UNIQUE_KEY VARCHAR2 20 Y TENANT_ID VARCHAR2 20 Y TENANT_NAME VARCHAR2 100 Y NETWORK_DOMAIN VARCHAR2 10 Y HOST_COUNT NUMBER 22 Y CLUSTER_COUNT NUMBER 22 Y ETL_PD NUMBER 22 Y ETL_TIME DATE 7 Y 打印了 UV_TENANT_CODE和UV_TENANT_RESOURCE_INFO两个表的列定义,UV_TENANT_CODE表包含列TENANT_ID,类型为NUMBER,长度为22,Y表示可为NULL,以此类推。 通过比较上面命令输出的文本,就可以比较两个数据库的表定义、索引、外键是否相同。 2)md5-table-data.py 这个脚本连接Oracle数据库,读取表的记录数、读取表内容并计算表的md5。 执行md5-table-data.py之前需要打开文件修改连接Oracle的参数: ora_username='paastest' ora_password='Paas1015' ora_conn_str='192.168.100.113:1521/nlpass01' 参数含义与get_object_from_ora.py相同。 对于有主键或唯一索引的表,将表的每个记录的所有列转为字符串并连接为一个长字符串,计算md5值,最终一个表得到一个md5值,md5值相同的表内容必然相同,脚本支持BLOB和CLOB类型。 对于没有主键或唯一索引的表,先比较源和目标记录个数是否相同,如果相同,仍可计算表的md5值并比较(每行执行异或操作)。 这个脚本有四个子命令,ora表示计算Oracle表的md5,ora-cnt表示计算Oracle表的行数,pg和pg-cnt是计算PostgreSQL表,这里不涉及。 Usage: md5-table-data.py [OPTIONS] COMMAND [ARGS]... Options: -h, --help Show this message and exit. Commands: ora Compute md5 of oracle tables. ora-cnt Compute row count of oracle tables. pg Compute md5 of postgresql tables. pg-cnt Compute row count of postgresql tables. a)md5-table-data.py ora-cnt --打印一个或多个表的行数 Usage: md5-table-data.py ora-cnt [OPTIONS] Compute row count of oracle tables. Options: -P, --parallel INTEGER Parallel threads -o, --output-file TEXT Output file -i, --input-file TEXT Intput file -t, --table-list TEXT Input table list e.g. -t "tb1,tb2,tb3" -h, --help Show this message and exit. 例如,打印UV_TENANT_RESOURCE_INFO和UV_TENANT_CODE表的行数: ./md5-table-data.py ora-cnt -t"UV_TENANT_RESOURCE_INFO,UV_TENANT_CODE" 选项-P表示并行数,一般用于表很多且表记录数很大时,如果指定,会开启多个线程,每个线程一个到Oracle的连接,将所有输入的表名自动分为若干个组,并行查询,如果不指定,默认1个线程。 选项-o表示输出文件的文件名,内容每个表一行,例如 选项-i表示输入文件名,输入文件每个表名一行,可以一次输入成百上千个表,当使用-i选项,且不指定-o时,默认输出到文件ora-cnt.txt。 选项-t表示输入的表名列表,与-i选项的含义相同。当使用-t选项时,结果直接打印到终端。 选项-n表示在计算表的md5时,只把前n条记录计算在内,这个功能用于校验正在增量同步的有主键表的前n条记录是否相同。 b)md5-table-data.py ora --打印一个或多个表的md5 Usage: md5-table-data.py ora [OPTIONS] Compute md5 of oracle tables. Options: -P, --parallel INTEGER Parallel threads -o, --output-file TEXT Output file -i, --input-file TEXT Intput file -t, --table-list TEXT Input table list e.g. -t "tb1,tb2,tb3" -n, --first-n INTEGER Compare first n record -h, --help Show this message and exit. 例如,对ext07文件里的表计算md5,结果输出到md5-ext07.txt md5-table-data.py ora -i ext07 -o md5-ext07.txt 文件ext07 的内容为: JOB_TRIGGER_LOG MK_ICLUL_MNT_SN_HS APP_MATURITY_CHECK_RESULT 文件md5-ext07.txt的内容为: JOB_TRIGGER_LOG : C868FC8DBF7EF298C3C8D5FDD9A9FA93 MK_ICLUL_MNT_SN_HS : C6F352A2CF9309F678880886DBC37B72 APP_MATURITY_CHECK_RESULT : 92C04839A5681D9AD16A4C1A07557209 ```