WEB开发网
开发学院数据库DB2 从 MySQL 或 PostgreSQL 迁移到 DB2 Express-C 阅读

从 MySQL 或 PostgreSQL 迁移到 DB2 Express-C

 2008-01-18 16:24:50 来源:WEB开发网   
核心提示: 容易使用、强大而且免费!这就是人们对 MySQL 和 PostgreSQL 的评价,但是,从 MySQL 或 PostgreSQL 迁移到 DB2 Express-C,您知道 DB2® 的一些版本具有同样(甚至更好的)品质吗?它们就是 DB2 Express 和 Express-C,它们是 DB2 产

容易使用、强大而且免费!这就是人们对 MySQL 和 PostgreSQL 的评价。但是,您知道 DB2® 的一些版本具有同样(甚至更好的)品质吗?它们就是 DB2 Express 和 Express-C,它们是 DB2 产品家族的成员,是专门为满足中小型企业的需要而设计的。Express 和 Express-C 是具有专业水准且容易使用的数据库,可以在 Windows® 和 Linux® 平台上运行。它们因简单的安装、图形用户界面、自管理功能和简化 DB2 使用方式的工具而闻名。而且,Express-C 是免费的!我们来看看从 MySQL/PostgreSQL 迁移到 DB2 是多么容易。

体系结构概述和对比

在 DB2、MySQL 和 PostgreSQL 之间有许多差异。我们先看看这三种数据库服务器在基本体系结构方面的一些差异和相似之处。

体系结构模型

MySQL 数据库服务器使用一种基于专用服务器线程的体系结构。

PostgreSQL 和 DB2 使用一种专用服务器进程模型体系结构。

存储引擎

MySQL 数据库使用可插入的存储引擎体系结构。

PostgreSQL 和 DB2 使用专用的存储引擎。

表空间模型

MySQL 对于 InnoDB 和 NDB 存储引擎使用表空间。

PostgreSQL 表空间可以跨越多个数据库。

DB2 表空间特定于一个数据库。

模式支持

PostgreSQL 和 DB2 具有真正的模式支持。

MySQL 不具有真正的模式支持。MySQL 中的模式可以被看作 MySQL 数据库。

数据库对象名是否是大小写敏感的

Linux 上的 MySQL 和 PostgreSQL 使用大小写敏感的数据库名、表名和列名。

所有平台上的 DB2 都使用大小写不敏感的名称。但是,DB2 只按照大写存储名称。

数组列

MySQL 和 DB2 不支持数组列。

PostgreSQL 支持数组列。

身份验证

DB2 使用各种外部安全机制来执行身份验证,比如操作系统、PAM、Kerberos、Active Directory、LDAP 等等。它还允许插入第三方安全模块。

PostgreSQL 按照许多不同方式之一执行身份验证。它可以使用数据库用户/角色、操作系统、PAM、Kerberos 等等,这取决于主机配置文件(pg_hba.conf)中的设置。

MySQL 在数据库级实现身份验证并对密码进行加密。

实例体系结构

DB2 实例管理不同的数据库,在同一台机器上可以有许多 DB2 实例。

PostgreSQL 的实例概念与数据库集群相似。

MySQL 实例与 DB2 数据库相似。

MySQL 和 PostgreSQL 数据库可以几乎每周都进行特性修改,但是 DB2 中的特性实现和修改要经过非常仔细的计划,这是因为有众多的业务依赖于使用 DB2 产品。请注意,在本文中我们使用 MySQL 5.1、PostgreSQL 8.0.3 和 DB2 V8.2 进行比较,所以在阅读本文时请考虑到这一点。

图 1、图 2 和 图 3 是 MySQL、PostgreSQL 和 DB2 的体系结构图。我们在阅读一些文档之后竭尽我们的能力绘制出 MySQL 和 PostgreSQL 的体系结构图。如果您发现不符合实际情况的地方,请告诉我们,我们会进行纠正。

MySQL

MySQL 使用一种基于线程的体系结构,而 PostgreSQL 和 DB2 采用基于进程的体系结构。正如在 图 1 中看到的,一个 MySQL 实例可以管理许多数据库。一个实例中的所有 MySQL 数据库共享一个公用的系统编目,INFORMATION_SCHEMA。

DB2 中的数据库是一个单独的实体,有自己的系统编目、表空间、缓冲池等等。DB2 实例管理不同的数据库,但是数据库并不共享表空间、日志、系统编目或临时表空间。

具有许多数据库的一个 MySQL 实例可以看作 DB2 中的一个数据库,而每个 MySQL 数据库相当于 DB2 中的一个模式。如果服务器上运行几个 MySQL 实例,每个实例管理几个数据库,那么可以采用以下迁移方式之一:

将每个 MySQL 实例迁移为同一 DB2 实例下的一个 DB2 数据库。

将每个 MySQL 实例迁移为只包含一个 DB2 数据库的 DB2 实例,并为每个 MySQL 数据库分配不同的模式。

注意: 当我们提到基于进程的体系结构时,指的是 UNIX® 平台,因为 Windows 上的模型是基于线程的体系结构。DB2 和 PostgreSQL 都是这样的。

在一个 DB2 连接的范围内只能访问一个数据库资源,而 MySQL 允许在同一个连接的范围内访问多个数据库资源。

MySQL 最有意思的特性之一是可插入的存储引擎。可以选择 MyISAM、InnoDB、Archive、Federated、Memory、Merge、Cluster、NDB 或 Custom 存储引擎。每个存储引擎具有不同的性质,可以根据自己的特定需求选择某一存储引擎。对于比较,我们发现 InnoDB 最接近于关系数据库。

图 1. MySQL 体系结构和进程概况

从 MySQL 或 PostgreSQL 迁移到 DB2 Express-C

MySQL 服务器进程(mysqld)可以创建许多线程:

一个全局线程(每个服务器进程有一个)负责创建和管理每个用户连接线程。

为处理每个新的用户连接创建一个线程。

每个连接线程还执行身份验证和查询。

在 Windows 上,有一个命名管道处理器线程,它针对命名管道连接请求执行与连接线程相同的工作。

一个信号线程处理警报并迫使长时间空闲的连接超时。

分配一个线程来处理关闭事件。

有一些线程在复制期间处理主服务器和从服务器的同步。

使用线程处理表刷新、维护任务等等。

MySQL 使用数据缓存、记录缓存、键缓存、表缓存、主机名缓存和特权缓存来缓存和检索服务器进程中所有线程所使用的不同类型的数据。

另外,MySQL 主进程(mysqld)具有用来处理数据库管理活动的线程,比如备份、恢复、并发控制等等。

PostgreSQL

PostgreSQL 实例(见 图 2)可以管理一个数据库集群。每个数据库有自己的系统编目,INFORMATION_SCHEMA 和 pg_catalog。所有数据库共享 pg_databases 作为公用系统表。每个数据库是一个单独的实体,数据库的集合称为集群。一个 PostgreSQL 实例可以管理一个数据库集群。一台服务器可以运行多个实例。

在逻辑上,PostgreSQL 数据库可以迁移到 DB2 数据库。这两种数据库都支持模式对象类型。不能从命名的连接访问其他数据库。

PostgreSQL 和 DB2 之间最显著的差异与表空间相关。PostgreSQL 表空间可以跨越多个数据库,而 DB2 表空间特定于一个数据库。

图 2. PostgreSQL 体系结构和进程概况

从 MySQL 或 PostgreSQL 迁移到 DB2 Express-C

PostgreSQL 会话由几个主进程组成:

postmaster 进程是一个主管进程,它生成其他进程并监听用户连接。

用户进程(比如 psql)用来处理交互式 SQL 查询。

postmaster 生成一个或多个名为 postgres 的服务器进程来处理用户的数据请求。

服务器进程通过信号量和共享内存来相互通信。

DB2

图 3 显示 DB2 的体系结构。这张图解释了 DB2 如何使用缓冲池在磁盘之间处理数据(文件、原始设备、目录等等)。DB2 使用一个连接集中器来处理大量连接。DB2 页清理器和预获取器异步地工作,各个进程单独处理重做日志活动。关于 DB2 中锁和进程的工作方式的详细描述,请参见 参考资料。

图 3. DB2 体系结构和进程概况

从 MySQL 或 PostgreSQL 迁移到 DB2 Express-C

DB2 会话由几个进程组成:

db2sysc,主 DB2 系统控制器,即引擎进程。

监听器进程,比如 db2tcpcm 和 db2ipccm,它们监听用户的连接请求。

一个或多个代表应用程序工作的代理。代理有两种类型:

db2agent 代表一个应用程序工作,并使用进程间通信或远程通信协议与其他代理通信。

db2agntp 用来在打开内部并行的情况下满足对数据库的客户机请求。

用户的进程(比如 db2)用来处理来自命令行的交互式查询。

db2bp —— 一个持久的后台进程,用于 DB2 Command Line Processor(CLP)。

db2disp —— 一个代理调度器进程,在启用连接集中器的情况下用于将连接分配给可用的协作代理。

db2fmcd —— 每个服务器的故障监视器协作守护进程。

db2fmd —— 每个实例的故障监视器守护进程。

db2resyn —— 一个重新同步管理器进程,用于处理两阶段提交。

db2dlock —— 一个 DB2 死锁探测器。

db2loggr —— 数据库日志读取器。

db2loggw —— 数据库日志写入器。

db2pclnr —— 缓冲池页清理器。

db2pfchr —— 缓冲池预获取器。

db2fmp —— 用于在服务器上 DB2 地址空间之外运行用户代码。

等等

DB2 服务器进程通过称为数据库管理器内存(Database Manager Memory)和数据库共享内存(Database Shared Memory)的内存区域相互通信,见 图 4。

图 4. DB2 数据库管理器(实例)和数据库共享内存体系结构

从 MySQL 或 PostgreSQL 迁移到 DB2 Express-C

特性对比

表 1 对比了 MySQL、PostgreSQL 和 DB2 特性。这不是一个完整的列表,但是对比了最常用的特性。

表 1. MySQL、PostgreSQL 和 DB2 特性对比

特性MySQLPostgreSQLDB2
实例 通过执行 MySQL 命令(mysqld)启动实例。一个实例可以管理一个或多个数据库。一台服务器可以运行多个 mysqld 实例。一个实例管理器可以监视 mysqld 的各个实例。 通过执行 Postmaster 进程(pg_ctl)启动实例。一个实例可以管理一个或多个数据库,这些数据库组成一个集群。集群是磁盘上的一个区域,这个区域在安装时初始化并由一个目录组成,所有数据都存储在这个目录中。使用 initdb 创建第一个数据库。 实例是一个 DB2 安装,它管理一个或多个数据库。在安装期间创建一个默认实例。使用 db2start 命令启动实例。还可以使用 db2icrt 命令在同一台机器上创建多个实例。在创建数据库本身之前,并不分配数据存储。数据库可以使用原始设备自己管理存储,或使用操作系统文件系统。环境变量 DB2INSTANCE 决定要连接哪个实例。
数据库 数据库是命名的对象集合,是与实例中的其他数据库分离的实体。一个 MySQL 实例中的所有数据库共享同一个系统编目。 数据库是命名的对象集合,每个数据库是与其他数据库分离的实体。每个数据库有自己的系统编目,但是所有数据库共享 pg_databases。 数据库是命名的对象集合,是与其他数据库分离的实体。数据库是在物理上和逻辑上独立的实体,不与其他数据库共享任何东西。一个 DB2 实例可以管理一个或多个数据库。
数据缓冲区 通过 innodb_buffer_pool_size 配置参数设置数据缓冲区。这个参数是内存缓冲区的字节数,InnoDB 使用这个缓冲区来缓存表的数据和索引。在专用的数据库服务器上,这个参数最高可以设置为机器物理内存量的 80%。 Shared_buffers 缓存。在默认情况下分配 64 个缓冲区。默认的块大小是 8K。可以通过设置 postgresql.conf 文件中的 shared_buffers 参数来更新缓冲区缓存。 在默认情况下分配一个缓冲池,并可以使用 CREATE BUFFERPOOL 命令添加其他缓冲池。默认的页大小在创建数据库时决定,可以是 4、8、16 或 32K。
数据库连接 客户机使用 CONNECT 或 USE 语句连接数据库,这时要指定数据库名,还可以指定用户 id 和密码。使用角色管理数据库中的用户和用户组。 客户机使用 connect 语句连接数据库,这时要指定数据库名,还可以指定用户 id 和密码。使用角色管理数据库中的用户和用户组。 客户机使用 connect 语句连接数据库,这时要指定数据库名,还可以指定用户 id 和密码。使用操作系统命令在数据库外创建用户和用户组。
身份验证 MySQL 在数据库级管理身份验证。 PostgreSQL 的身份验证取决于主机配置。 DB2 使用 API 通过各种实现(比如 Kerberos、LDAP、Active Directory 和 PAM)在操作系统级对用户进行身份验证,它的可插入身份验证体系结构允许插入第三方模块。
加密 可以在表级指定密码来对数据进行加密。还可以使用 AES_ENCRYPT 和 AES_DECRYPT 函数对列数据进行加密和解密。可以通过 SSL 连接实现网络加密。 可以使用 pgcrypto 库中的函数对列进行加密/解密。可以通过 SSL 连接实现网络加密。 可以使用 DB2 提供的加密和解密方法对列数据进行加密/解密。如果在实例级选择 DATA_ENCRYPT 身份验证方法,那么可以对客户机和服务器之间的网络通信进行加密。
审计 可以对 querylog 执行 grep。 可以在表上使用 PL/pgSQL 触发器来进行审计。 DB2 提供的 db2audit 实用程序可以提供详细的审计,而不需要实现基于触发器或日志的审计。
查询解释 使用 EXPLAIN 命令查看查询的解释计划。 使用 EXPLAIN 命令查看查询的解释计划。 DB2 提供的 GUI 和命令行工具可以用来查看查询的解释计划。它还可以从 SQL 缓存捕获查询并生成解释计划。可以使用工具查看所有存储过程中的 SQL 的解释计划。
备份、恢复和日志InnoDB 使用写前(write-ahead)日志记录。支持在线和离线完全备份以及崩溃和事务恢复。 在数据目录的一个子目录中维护写前日志。支持在线和离线完全备份以及崩溃、时间点和事务恢复。 使用写前日志记录。支持完全、增量、delta 和表空间级在线/离线备份和恢复。支持崩溃、时间点和事务恢复。
JDBC 驱动程序 可以从 参考资料 下载 JDBC 驱动程序。 可以从 参考资料 下载 JDBC 驱动程序。 支持 Type-2 和 Type-4(Universal)驱动程序。JDBC 驱动程序是 DB2 产品的一部分。
表类型 取决于存储引擎。例如,NDB 存储引擎支持分区表,内存引擎支持内存表。 支持临时表、常规表以及范围和列表类型的分区表。不支持哈希分区表。 支持用户表、临时表、常规表以及范围、哈希和多维簇类型的分区表。
索引类型 取决于存储引擎。MyISAM:BTREE,InnoDB:BTREE。 支持 B-树、哈希、R-树和 Gist 索引。 支持 B-树和位图索引。
约束 支持主键、外键、惟一和非空约束。对检查约束进行解析,但是不强制实施。 支持主键、外键、惟一、非空和检查约束。 支持主键、外键、惟一、非空和检查约束。
存储过程和用户定义函数 支持 CREATE PROCEDURE 和 CREATE FUNCTION 语句。存储过程可以用 SQL 和 C++ 编写。用户定义函数可以用 SQL、C 和 C++ 编写。 虽然使用术语存储过程,但是只支持 CREATE FUNCTION 语句。用户定义函数可以用 PL/pgSQL(专用的过程语言)、SQL 和 C 编写。 支持 CREATE PROCEDURE 和 CREATE FUNCTION 语句。存储过程可以用 SQL(SQL PL)、C、Java、COBOL 和 REXX 编写。用户定义函数可以用 SQL(SQL PL)、C 和 Java 编写。
触发器 支持行前触发器、行后触发器和语句触发器,触发器语句用过程语言复合语句编写。 支持行前触发器、行后触发器和语句触发器,触发器过程用 C 编写。 支持行前触发器、行后和语句触发器、instead of 触发器和包含 SQL PL 复合语句的触发器。可以从触发器调用存储过程。
系统配置文件 my.conf Postgresql.conf Database Manager Configuration
数据库配置 my.conf Postgresql.conf Database Configuration
客户机连接文件 my.conf pg_hba.conf System Database Directory

Node Directory

XML 支持 有限的 XML 支持。 有限的 XML 支持。 为访问 XML 数据提供丰富的支持。DB2 Viper(V9)是第一个以原生形式存储/检索 XML 的混合型数据库。
数据访问和管理服务器 OPTIMIZE TABLE —— 回收未使用的空间并消除数据文件的碎片

myisamchk -analyze —— 更新查询优化器所使用的统计数据(MyISAM 存储引擎)

mysql —— 命令行工具

MySQL Administrator —— 客户机 GUI 工具

Vacuum —— 回收未使用的空间

Analyze —— 更新查询优化器所使用的统计数据

psql —— 命令行工具

pgAdmin —— 客户机 GUI 工具

Reorg —— 用来重新整理数据并消除数据碎片

Runstat —— 收集优化器所使用的统计数据

CLP —— 命令行工具

Control Center —— 客户机 GUI 工具

并发控制 支持表级和行级锁。InnoDB 存储引擎支持 READ_COMMITTED、READ_UNCOMMITTED、REPEATABLE_READ 和 SERIALIZABLE。使用 SET TRANSACTION ISOLATION LEVEL 语句在事务级设置隔离级别。 支持表级和行级锁。支持的 ANSI 隔离级别是 Read Committed(默认 —— 能看到查询启动时数据库的快照)和 Serialization(与 Repeatable Read 相似 —— 只能看到在事务启动之前提交的结果)。使用 SET TRANSACTION 语句在事务级设置隔离级别。使用 SET SESSION 在会话级进行设置。 支持表级和行级锁以及 4 个隔离级别:RR(可重复读)、RS(读可靠)、CS(默认 —— 游标可靠)和 UR(未提交读)。使用 SET ISOLATION 在会话级、使用 WITH 子句在 SQL 语句级或使用数据库配置参数在数据库级设置隔离级别。

到目前为止,我们已经看到了 MySQL、PostgreSQL 和 DB2 在体系结构和特性方面的一些差异。现在就来研究这些数据库服务器在数据类型方面的差异。

MySQL、PostgreSQL 和 DB2 之间的数据类型对比

SQL ANSI 标准规定了关系数据库系统中使用的数据类型的规则。但是,并非每种数据库平台都支持标准委员会定义的每个数据类型。而且,特定数据类型的厂商实现可能与标准的规定不同,甚至在所有数据库厂商之间互不相同。因此,尽管许多 MySQL、PostgreSQL 和 DB2 数据类型在名称和/或含义方面是相似的,但是也有许多需要注意的差异。

表 2 列出最常用的 DB2 数据类型。我们在后面的小节中提供 MySQL 和 PostgreSQL 数据类型与 DB2 最接近的匹配。

尽管 DB2 对 SQL 有一些限制(比如对约束名的长度限制、数据类型限制等等),但是各个新版本正在系统化地消除这些限制。

表 2. DB2 数据类型

数据类型 说明
BIGINT存储有符号或无符号整数,使用 8 字节的存储空间。
BLOB

BLOB(n)

存储长度可变的二进制数据,长度最大为 2 GB。超过 1 GB 的长度不进行日志记录。
CHAR(n)

CHARACTER(n)

存储固定长度的字符数据,长度最大为 254 字节。使用 ‘n’ 字节的存储空间。
CHAR(n) FOR BIT DATA存储固定长度的二进制值。
CLOB

CLOB(n)

存储长度可变的字符数据,长度最大为 2 GB。超过 1 GB 的长度不进行日志记录。
DATE存储日历日期,不包含天内的时间。使用 4 字节的存储空间。
DEC(p,s)

DECIMAL(p,s)

NUM(p,s)

NUMERIC(p,s)

采用精度(p)1 到 31 和刻度(s)0 到 31 来存储数值。使用 (p/2) +1 字节的存储空间。
DOUBLE

DOUBLE PRECISION

FLOAT

存储浮点数,使用 8 字节的存储空间。
FLOAT(p) 采用精度(p)1 到 53 来存储数值。如果 p <= 24,那么相当于 REAL。如果 p >= 25,那么相当于 DOUBLE PRECISION。
GRAPHIC(n) 用于 National Language Support(NLS)和长度固定的字符串(常常是 DBCS),长度最大为 127 字节。对于双字节字符集,使用 n*2 字节的存储空间;对于单字节字符集,使用 n 字节的存储空间。
INT

INTEGER

存储有符号或无符号整数,使用 4 字节的存储空间。
REAL 存储浮点数,使用 4 字节的存储空间。
SMALLINT 存储有符号和无符号整数,使用 2 字节的存储空间。
TIME 存储天内的时间,使用 3 字节的存储空间。
TIMESTAMP 存储日期(年、月、日)和时间(小时、分钟、秒),最大精度 6 毫秒。使用 10 字节的存储空间。
VARCHAR(n)

CHAR VARYING(n)

CHARACTER VARYING(n)

存储长度可变的字符数据,长度最大为 32,672 字节。使用 n+2 字节的存储空间。
VARCHAR(n) FOR BIT DATA 存储长度可变的二进制数据。使用 n 字节的存储空间。
VARGRAPHIC(n) 存储长度可变的双字节字符数据,长度最大为 16,336 字符。使用 (n*2)+2 字节的存储空间。

MySQL 和 DB2

下面的表中描述 MySQL 和 DB2 数据类型的定义和差异。表 3 描述最常用的 MySQL 数据类型。表 4 将 MySQL 数据类型映射到最接近的 DB2 数据类型。

MySQL 可以使用 SERIAL 别名作为数据类型,这相当于 BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE。

BOOL 或 BOOLEAN 是 TINYINT(1) 的同义词。在 MySQL 中,DECIMAL 的最大位数是 65,支持的最大小数位是 30。如果为 DECIMAL 指定 UNSIGNED,那么不允许负数。

时间戳列不支持毫秒。

表 3. MySQL 数据类型

数据类型 说明
BIT 固定长度的位串。
BOOLEAN 存储逻辑布尔值(true/false/unknown),可以是 TRUE、true 和 1;FALSE、false 和 0。
TINYBLOB 用于存储二进制对象(比如图形)的原始二进制数据,最大 255 字节。
BLOB 用于存储二进制对象(比如图形)的原始二进制数据,最大 65,535 字节。
MEDIUMBLOB 用于存储二进制对象(比如图形)的原始二进制数据,最大 16,777,215 字节。
LONGBLOB 用于存储二进制对象(比如图形)的原始二进制数据,最大 4GB。
CHAR(n)

CHARACTER(n)

包含固定长度的字符串,用空格填充到长度 n。
DATE 用 3 字节的存储空间存储日历日期(年、月、日)。
DATETIME 用 8 字节的存储空间存储日历日期和天内的时间。
YEAR 用 1 字节的存储空间存储两位或四位格式的年份。
DECIMAL(p,s)

NUMERIC(p,s)

存储精确的数值,精度(p)最高为 65,刻度(s)为 30 或更高。
FLOAT 存储浮点数,限制由硬件决定。单精度浮点数精确到大约 7 位小数。UNSIGNED 属性不允许负数。
DOUBLE

REAL

存储双精度浮点数,限制由硬件决定。双精度浮点数精确到大约 15 位小数。UNSIGNED 属性不允许负数。
TINYINT 存储有符号或无符号 1 字节整数。
SMALLINT 存储有符号或无符号 2 字节整数。
MEDIUMINT 存储有符号或无符号 3 字节整数。
INTEGER 存储有符号或无符号 4 字节整数。
BIGINT 存储有符号或无符号 8 字节整数。
TINYTEXT 用于存储最多 255 字节的字符串数据。
TEXT 用于存储最多 65,535 字节的字符串数据。
MEDIUMTEXT 用于存储最多 16,777,215 字节的字符串数据。
LONGTEXT 用于存储最多 4GB 的字符串数据。
TIME 用 3 字节的存储空间存储天内的时间。
TIMESTAMP 用 4 字节的存储空间存储日期和时间。如果没有提供有效值的话,TIMESTAMP 列会自动设置为最近操作的日期和时间。
VARCHAR(n)

CHARACTER VARYING(n)

CHARACTER VARYING

存储长度可变的字符串,最大长度由 n 指定。末尾的空格不存储。
ENUM 一种串对象,它的值只能是从值列表 ‘value1’, ‘value2’, ..., NULL 中选择的一个值。
SET 一种串对象,它可以具有零个或更多的值,这些值必须从值列表 ‘value1’, ‘value2’, ... 中选择。
BINARY 与 CHAR 类型相似,但是存储二进制字节串而不是字符串。
VARBINARY 与 VARCHAR 类型相似,但是存储二进制字节串而不是字符串。

表 4. MySQL 数据类型到 DB2 的映射

MYSQL DB2 说明
BIT CHAR(n) FOR BIT DATA 关于用来简化迁移的 UDF 的细节,请参阅 参考资料。
BOOLEAN SMALLINT 或 CHAR(1) 使用检查约束来实施规则。
TINYBLOB VARCHAR(255) FOR BIT DATA 可以使用 BLOB(255) 或 VARCHAR(255) FOR BIT DATA。在这种情况下,使用 VARCHAR 效率比较高。
BLOB BLOB(64K) 如果长度小于 32K,那么考虑使用 VARCHAR(n) FOR BIT DATA。
MEDIUMBLOB BLOB(16M) 可以使用 NOT LOGGED 改进性能。
LONGBLOB BLOB(2G) 支持的 BLOB 最大长度是 2GB。
CHAR(n)

CHARACTER(n)

CHAR(n)

CHARACTER(n)

在 DB2 中,‘n’ 的最大值为 254。
DATE DATE -
DATETIME TIMESTAMP 可以使用特殊寄存器 CURRENT TIMEZONE 对日期进行转换。
YEAR SMALLINT 可以使用检查约束实施 YEAR 规则。
DECIMAL(p,s)

NUMERIC(p,s)

DECIMAL(p,s)

NUMERIC(p,s)

如果 p 大于 31,那么使用 DOUBLE。
FLOAT REAL _
DOUBLE

REAL

DOUBLE _
SMALLINT SMALLINT 使用检查约束限制值小于 256。
SMALLINT SMALLINT _
MEDIUMINT INTEGER 如果需要,使用检查约束限制最大长度。
INTEGER INTEGER

INT

_
BIGINT BIGINT _
TINYTEXT VARCHAR(255) 对于少于 32K 的数据,使用 VARCHAR 比较高效。
TEXT CLOB(64K) DB2 允许为 CLOB 或 BLOB 指定长度参数。指定需要的长度,而不要使用 TINY、MEDIUM 或 LONG CLOB。
MEDIUMTEXT CLOB(16M) _
LONGTEXT CLOB(2G) 最大长度是 2GB。如果使用 LOGGED,那么 BLOB 或 CLOB 的最大长度为 1GB。使用 NOT LOGGED 选项可以提高性能。
TIME TIME _
TIMESTAMP TIMESTAMP _
VARCHAR(n)

CHARACTER VARYING(n)

VARCHAR(n)

CHARACTER VARYING(n)

如果长度小于 32K,那么使用 VARCHAR。
ENUM VARCHAR(n) 使用检查约束来实施规则。
SET VARCHAR(n) 使用检查约束来实施规则。
BINARY CHAR(n) FOR BIT DATA 如果 n 小于 254,那么使用 CHAR(n) FOR BIT DATA;否则使用 VARCHAR(n) FOR BIT DATA。
VARBINARY VARCHAR(n) FOR BIT DATA 如果 ‘n’ 小于 32K,那么使用 VARCHAR;否则使用 BLOB。

PostgreSQL 和 DB2

下面两个表描述 DB2 和 PostgreSQL 数据类型的定义和差异。表 5 描述最常用的 PostgreSQL 数据类型。表 6 将 PostgreSQL 数据类型映射到最接近的 DB2 数据类型。

PostgreSQL 使用特殊的网络地址类型,比如 inet、cidr、macaddr。这些数据类型迁移到 DB2 中的 VARCHAR 数据类型。

PostgreSQL 还支持几何数据类型。迁移工具不处理几何数据类型。目前,我们假设不太需要支持对这种数据类型进行转换。如果您使用几何数据类型,那么请告诉我们,我们将在工具中提供补丁。

处理 PostgreSQL 中的位串数据类型需要在应用程序中做一些修改。目前,工具不提供这种支持。如果需要这种支持,请告诉我们。

PostgreSQL 还支持多维数组,它们最好迁移成 DB2 中的子表。但是,工具目前不支持多维数组。

表 5. PostgreSQL 数据类型

数据类型 说明
BIGSERIAL

SERIAL8

存储自动递增的惟一整数,最多 8 字节。
BIT 固定长度的位串。
BIT VARYING(n)

VARBIT(n)

可变长度的位串,长度为 n 位。
BOOLEAN 存储逻辑布尔值(true/false/unknown),可以是 TRUE、t、true、y、yes 和 1,或者 FALSE、f、false、n、no 和 0。
BYTEA 用于存储大型二进制对象(比如图形)的原始二进制数据。使用的存储空间是 4 字节加上二进制串的长度。
CHAR(n)

CHARACTER(n)

包含固定长度的字符串,用空格填充到长度 n。
DATE 用 4 字节的存储空间存储日历日期(年、月、日)。
DATETIME 存储日历日期和天内的时间。
DECIMAL(p,s)

NUMERIC(p,s)

存储精确的数值,精度(p)和刻度(s)为 0 或更高。
FLOAT4

REAL

存储浮点数,精度为 8 或更低和 6 个小数位。
FLOAT8

DOUBLE PRECISION

存储浮点数,精度为 16 或更低和 15 个小数位。
SMALLINT 存储有符号或无符号 2 字节整数。
INTEGER 存储有符号或无符号 4 字节整数。
INT8

BIGINT

存储有符号或无符号 8 字节整数。
SERIAL

SERIAL4

存储自动递增的惟一整数值,最多 4 字节存储空间。
TEXT 存储长度可变的大型字符串数据,最多 1 GB。PostgreSQL 自动压缩 TEXT 字符串。
TIME (WITHOUT TIME ZONE |

WITH TIME ZONE)

存储天内的时间。如果不存储数据库服务器的时区,就使用 8 字节的存储空间;如果存储时区,就使用 12 字节。
TIMESTAMP (WITHOUT TIME ZONE |

WITH TIME ZONE)

存储日期和时间。可以存储或不存储数据库服务器的时区,使用 8 字节存储空间。
VARCHAR(n)

CHARACTER VARYING(n)

CHARACTER VARYING

存储可变长度的字符串,最大长度为 n。不存储末尾的空格。

表 6. PostgreSQL 数据类型到 DB2 的映射

POSTGRESQL DB2 说明
BIGSERIAL

SERIAL8

BIGINT 使用 IDENTITY 属性模拟自动递增特性。
BIT CHAR(n) FOR BIT DATA 对于长度最大为 254 字节的字符串。
BIT VARYING(n)

VARBIT(n)

VARCHAR(n) FOR BIT DATA 用于 32,672 字节以下的字符串。
BYTEA BLOB 用于 32K 和 2GB 字节之间的数据。
BOOLEAN 无布尔类型 使用 CHAR(1) 或 SMALLINT。
CHAR(n)

CHARACTER (n)

CHAR(n) 最多 254 字节。
DATE DATE 可以使用特殊寄存器 CURRENT TIMEZONE 对日期进行转换。
DATETIME TIMESTAMP 可以使用特殊寄存器 CURRENT TIMEZONE 对日期进行转换。
DECIMAL(p,s)

NUMERIC(p,s)

DECIMAL(p,s) 如果精度大于 31,那么使用 DOUBLE。
FLOAT4

REAL

REAL 可以使用 NUMERIC 或 FLOAT。
FLOAT8

DOUBLE PRECISION

DOUBLE PRECISION 对于大数值使用 DOUBLE PRECISION,如果精度小于 31,那么使用 NUMERIC。
SMALLINT SMALLINT _
INTEGER INTEGER _
INT8

BIGINT

BIGINT _
VARCHAR(n)

CHARACTER VARYING(n)

CHARACTER VARYING

VARCHAR(n) 如果 ‘n’ 小于等于 32K。DB2 要求指定 ‘n’,而 PostgreSQL 不要求指定 ‘n’ 的值。
SERIAL

SERIAL4

INTEGER 使用 IDENTITY 属性。
TEXT VARCHAR(n)

CLOB

如果长度小于 32K,那么使用 VARCHAR;如果大于 32K,那么使用 BLOB。
TIME (WITHOUT TIME ZONE | WITH TIME ZONE) TIME 没有时区。
TIMESTAMP (WITHOUT TIME ZONE | WITH TIME ZONE) TIMESTAMP 没有时区。

在 PostgreSQL 中,即使在引用的表中数据类型不同,也可以创建外键约束。例如,如果父表的惟一键的数据类型是整数,那么可以在子表中数据类型为 char(10) 的列上创建外键。工具将转换这个约束,但是会失败,因为 DB2 不允许数据类型不同。

现在,我们已经研究了 MySQL、PostgreSQL 和 DB2 之间的数据类型差异,以及一些高级特性差异。现在就讨论用三个简单的步骤迁移到 DB2 的过程。

步骤 1:安装 DB2 Express/Express-C

DB2 Express 和 Express-C 可以安装在 Linux 或 Windows 系统上,要求运行 32 或 64 位硬件,最多 2 个处理器和 4GB 可寻址内存。DB2 Express-C 可以很容易地升级到 DB2 Express 和 Workgroup and Enterprise Server Editions,不需要修改数据库或 C/C++、Java、.NET 和 PHP 等应用程序。

Linux 和 Windows 上的安装过程基本上是相同的。DB2 Express 的安装涉及以下简单步骤:

使用本地管理员帐号(Windows)或作为根用户(Linux)登录到系统中。

在 Windows 上执行 setup.exe,Setup 启动面板出现。

在 Linux 上执行 setup 进行 GUI 安装,或运行 db2install 进行命令行安装。

如果使用 db2install,那么需要手工执行创建 DB2 实例等步骤。

在 GUI 安装中,选择 install product 来启动 Setup 向导。

按照安装向导的指示进行操作并在提示时提供输入。

对于嵌入 DB2 Express-C 的产品,可以使用响应文件执行静安装。

还要注意几点:

设置 DB2 实例所有者:

Windows 上的默认用户 id 是 db2admin,在 Linux 上是 db2inst1。

在 Linux 上的一个差异是,除了实例所有者 id 之外,还需要为 fenced 用户提供另一个用户 id。fenced 用户 id 用来运行外部 C 或 Java 存储过程和用户定义函数。

如果指定的用户不存在,那么就创建它并授予所需的特权。

如果使用现有的用户 id,那么它必须具有管理员特权(Windows)。

在安装期间,创建默认的实例:

在 Windows 上,它称为 DB2。

在 Linux 上,它称为 db2inst1。

在默认情况下,DB2 服务器被配置为使用 TCPIP(端口 50000)。可以使用 protocols 按钮修改这个设置。

在安装之后,First Steps 将启动,可以用来帮助创建第一个数据库,这个数据库称为 SAMPLE。

步骤 2:使用工具迁移 DDL 和数据

修改 PostgreSQL 设置

如果要从远程机器连接到 PostgreSQL 数据库,那么要为 PostgreSQL 服务器启用远程客户机连接,如下所示:

修改 pg_hba.conf 以允许远程连接。

找到 postgres 数据库目录中的 pg_hba.conf 文件。在 pg_hba.conf 文件中添加一行以允许对 PostgreSQL 数据库进行远程 TCPIP 连接,如下所示:

host  all     all     9.0.0.0 255.0.0.0   trust

第四个参数指定 IP 地址的范围,第五个参数指定子网掩码。在上面的示例中,允许以 9 开头的所有 IP 地址连接 PostgreSQL 数据库。

从命令行启动 Postgres 数据库服务器。$ pg_ctl -D /home/postgres/testdb -o -i -l logfile start

进行迁移所需的软件

JDBC 驱动程序 PostgreSQL

要连接 PostgreSQL,需要使用 JDBC 驱动程序。在编写本文时,我们使用 PostgreSQL 8.0.3 和 JDBC 驱动程序 8.0.315。可以从 参考资料 下载 PostgreSQL 的 JDBC 驱动程序。请注意,本文提供的工具并不包含 PostgreSQL JDBC 驱动程序。

JDBC 驱动程序 MySQL

我们使用 MySQL Connector/J 3.1 V 3.1.12 连接 MySQL 数据库。可以从 参考资料 下载 MySQL 数据库的 JDBC 驱动程序。提供的工具并不包含 JDBC 驱动程序。

安装 JDBC 驱动程序之后,修改 CLASSPATH 参数以包含 JDBC 驱动程序。

IBM JDK 5.0

这个工具只用 Java JDK 5.0 测试过。可以使用 Sun 或 IBM Java JDK 5.0 运行这个工具。从 参考资料 下载 IBM 5.0 JDK。

设置迁移工具

在 UNIX 系统上,可以将这个工具安装在 DB2 实例用户主目录中或者其他用户的主目录中,这些用户必须有运行 DB2 LOAD 实用程序所需的权限。

从 下载 一节下载这个工具之后,将文件解压到一个目录中。这个工具在 IBMExtract.jar 文件中提供。更新个人配置文件中的 CLASSPATH 变量以包含这个工具和所需的 JDBC 驱动程序。例如,以下示例展示如何在 CLASSPATH 中包含 IBMExtract.jar、PostgreSQL 和 MySQL JDBC 驱动程序。

export JAVA_HOME=/opt/ibm/java2-i386-50
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=$HOME/java/lib/IBMExtract.jar:$CLASSPATH
export CLASSPATH=$HOME/java/lib/postgresql-8.0-315.jdbc3:$CLASSPATH
export CLASSPATH=$HOME/java/lib/mysql-connector-java-3.1.12-bin.jar:$CLASSPATH

在 Windows 系统上,通过 Control Panel -> System -> Advanced -> Environment Variables 更新 CLASSPATH 环境变量。

工具结构

这个工具有两个组件。第一个组件(ibm.GenInput)生成供第二个组件(ibm.GenerateExtract)使用的输入文件。用户可以修改第一个组件生成的输入文件,删除迁移所不需要的表。还可以编辑输入文件,指定要在 DB2 中创建的表作为定制查询的结果。

ibm.GenInput

运行第一个组件的脚本是 geninput shell 脚本(Linux)和 geninput.cmd(Windows)。要连接 MySQL/PostgreSQL 数据库,需要指定适合自己环境的正确参数。需要修改以下脚本中的 DBVENDOR、SERVER、DATABASE、PORT、DBUID 和 DBPWD 参数。脚本如下所示:

清单 1. 在 Windows 上运行的脚本(geninput.cmd)

@echo off
cls
ECHO Executed by: %USERNAME% Machine: %COMPUTERNAME% On %OS% %DATE% %TIME%
ECHO.
ECHO -------------------------------------------------------------------
ECHO Program to perform MySQL/PostgreSQL to DB2 Migration
ECHO -------------------------------------------------------------------
ECHO.
if "%1" == "" (
 echo Usage : geninput.cmd dbname
 goto end
)
SET DBVENDOR=postgres
SET DB2SCHEMA=%1
SET SERVER=server.ibm.com
SET DATABASE=%1
SET PORT=5432
SET DBUID=postgres
SET DBPWD=pwd
%JAVA_HOME%injava -DINPUT_DIR=.migr -cp %CLASSPATH% ibm.GenInput
 %DBVENDOR% %DB2SCHEMA% %SERVER% %DATABASE% %PORT% %DBUID% %DBPWD%
:end       

清单 2. 在 Linux 上运行的脚本(geninput)

#!/bin/bash
if [ "$1" = "" ] ; then
 echo Usage : geninput dbname
 exit 1
fi
DBVENDOR=postgres
DB2SCHEMA=$1
SERVER=server.ibm.com
DATABASE=$1
PORT=5432
DBUID=postgres
DBPWD=pwd
java -DINPUT_DIR=$PWD -cp $CLASSPATH ibm.GenInput $DBVENDOR $DB2SCHEMA
   $SERVER $DATABASE $PORT $DBUID $DBPWD          

存储工具的输入文件的 INPUT 目录通过 VM 参数设置为 -DINPUT_DIR。在上面的脚本中,它指定为当前目录。程序将在当前工作目录中创建一个 input 目录。

输入文件创建参数

表 7. GenInput 参数

参数名 说明
Java program ibm.GenInput 这是主 Java 程序。
DBVENDOR postgres 或 mysql 指定 postgres 还是 mysql。
DB2SCHEMA schema_name 指定要将来自源数据库的表导入到哪个 DB2 模式中。
SERVER Hostname PostgreSQL 或 MySQL 数据库服务器的主机名或 IP 地址。
DATABASE dbname PostgreSQL 或 MySQL 数据库的名称。
PORT nnn 要连接的端口号。连接 MySQL/Postgresql 的默认端口号是 3306/5432。
DBUID uid MySQL 或 PostgreSQL 数据库用户 id。
DBPWD pwd MySQL 或 PostgreSQL 数据库密码。

输入文件的结构

工具的第一个组件(ibm.GenInput)生成供第二个组件(ibm.GenerateExtract)使用的输入文件。输入文件的结构如下,可能需要修改文件的查询部分以便根据对源数据库的查询创建表。

DB2_Schema_Name.Actual_Table_Name:Table Query

文件的内容示例如下:

ama.ama_msa:SELECT * FROM public.ama_msa
ama.ama_mti:SELECT * FROM public.ama_mti
ama.ama_pe:SELECT * FROM public.ama_pe
ama.ama_pmsa:SELECT * FROM public.ama_pmsa
ama.ama_schools:SELECT * FROM public.ama_schools
ama.ama_specialties_group:SELECT * FROM public.ama_specialties_group

ibm.GenerateExtract

卸载数据并为 DB2 生成 DDL 的脚本是 unload shell 脚本(Linux)和 unload.cmd 脚本(Windows)。需要根据自己的 MySQL/PostgreSQL 数据库修改以下连接参数:DBVENDOR、SERVER、PORT、DBUID 和 DBPWD。用于 Windows 和 Linux 环境的 unload 脚本如下所示:

清单 3. 在 Windows 上运行的脚本(unload.cmd)

@echo off
cls
ECHO Executed by: %USERNAME% Machine: %COMPUTERNAME% On %OS% %DATE% %TIME%
ECHO.
ECHO -------------------------------------------------------------------
ECHO Program to perform MySQL/PostgreSQL to DB2 Migration
ECHO -------------------------------------------------------------------
ECHO.
if "%1" == "" (
 echo Usage : unload.cmd dbname
 goto end
)
SET TABLES=input%1.tables
SET COLSEP=~
SET DBVENDOR=postgres
SET NUM_THREADS=5
SET SERVER=server.ibm.com
SET DATABASE=%1
SET PORT=5432
SET DBUID=postgres
SET DBPWD=pwd
SET GENDDL=true
SET UNLOAD=true
SET FETCHSIZE=100
%JAVA_HOME%injava -DOUTPUT_DIR=output%1 -cp %CLASSPATH%
 ibm.GenerateExtract %TABLES% %COLSEP% %DBVENDOR% %NUM_THREADS% %SERVER%
 %DATABASE% %PORT% %DBUID% %DBPWD% %GENDDL% %UNLOAD% %FETCHSIZE%
:end

清单 4. 在 Linux 上运行的脚本(unload)

#!/bin/bash
if [ "$1" = "" ] ; then
 echo Usage : unload dbname
 exit 1
fi
TABLES=$PWD/input/$1.tables
COLSEP=~
DBVENDOR=postgres
NUM_THREADS=5
SERVER=db2lab9.dfw.ibm.com
DATABASE=$1
PORT=5432
DBUID=postgres
DBPWD=db2mig
GENDDL=true
UNLOAD=true
FETCHSIZE=100
java -DOUTPUT_DIR=$PWD/output/$1 -cp $CLASSPATH ibm.GenerateExtract
  $TABLES $COLSEP $DBVENDOR $NUM_THREADS $SERVER $DATABASE
  $PORT $DBUID $DBPWD $GENDDL $UNLOAD $FETCHSIZE

我们将通过 JVM 的 -D 开关将指定的 OUTPUT_DIR 作为参数传递给Java 程序。在这个示例中,它定义为 output/$1,这是通过 unload 命令指定的输出/数据库名。

卸载参数

表 8. GenerateExtract 参数

参数名 说明
Java program Ibm.GenerateExtract 这是主 Java 程序。
TABLES FileName 这是包含表名和 SQL 查询的文件,这些表和查询用来为 DB2 生成 DDL 和卸载数据。这个文件是在第一步中生成的。
COLSEP ~ 列分隔符。在这个示例中,选用波浪号字符(~)。如果波浪号字符在自己的 Unix 环境中有特殊意义,那么可以加上反斜线前缀。在 Linux 平台上,波浪号用于展开成主目录名。在 Windows 平台上,可以指定波浪号而不需要加反斜线前缀。
DBVENDOR postgres 数据库厂商名称。如果对 MySQL 数据库运行这个工具,那么指定 mysql;对于 PostgreSQL,使用 postgres 值。
NUM_THREADS nn Java 程序将运行的线程数量。
SERVER Hostname MySQL/PostgreSQL 数据库服务器的主机名或 IP 地址。如果在本地主机上运行,那么可以指定 localhost。
DATABASE dbname 将迁移到 DB2 的 MySQL/PostgreSQL 数据库的名称。
PORT nnn 用来连接 MySQL/PostgreSQL 数据库的端口号。MySQL/PostgreSQL 的默认端口分别是 3306/5432。
DBUID uid MySQL/PostgreSQL 数据库服务器的用户 id。
DBPWD pwd MySQL/PostgreSQL 用户 id 的密码。
GENDDL true 这个值可以是 true 或 false。这指示工具为要卸载的表生成 DDL。
UNLOAD true 这个值可以是 true 或 false。这指示工具将数据卸载到 OUTPUT_DIR 目录。OUTPUT_DIR 是通过 VM 的 -D 开关指定的。
FETCHSIZE 1000 这是重要的参数,可以指定为 100 或更高。如果这个值设置得非常大,那么可能会耗光内存,因为 MySQL/PostgreSQL JDBC 驱动程序试图将大量数据放在内存中。如果有大量内存,那么可以通过增加这个参数来改进性能。如果遇到 “内存耗尽” 问题,那么降低这个参数。

驱动程序属性

这个工具使用一个驱动程序属性文件来读取 MySQL/PostgreSQL 数据库的 JDBC 驱动程序信息。这个属性文件包含在 JAR 文件中。

postgres=org.postgresql.Driver
mysql=com.mysql.jdbc.Driver      

URL 属性

这个工具使用一个 URL 属性文件来读取 MySQL/PostgreSQL 数据库的 JDBC 驱动程序 URL 信息。这个属性文件包含在 JAR 文件中。

postgres=jdbc:postgresql://
mysql=jdbc:mysql://      

映射属性

MySQL/PostgreSQL 与 DB2 之间的数据类型映射由一个数据类型映射属性文件控制。这个文件包含在 JAR 文件中。如果需要修改 MySQL/PostgreSQL 与 DB2 之间的数据类型映射属性,那么只需修改这个文件,而不需要修改程序。

清单 5. 数据类型映射属性文件

POSTGRES.INT=INTEGER
POSTGRES.INT2=SMALLINT
POSTGRES.INT4=INTEGER
POSTGRES.INT8=INTEGER
POSTGRES.SERIAL4=INTEGER
POSTGRES.SERIAL8=INTEGER
POSTGRES.BOOLEAN=SMALLINT
POSTGRES.BYTEA=BLOB
POSTGRES.VARCHAR=VARCHAR;VARLENGTH=TRUE;DEFAULT=255
POSTGRES.CHARACTER=CHAR;VARLENGTH=TRUE
POSTGRES.BPCHAR=CHAR;VARLENGTH=TRUE
POSTGRES.DATE=DATE
POSTGRES.FLOAT4=REAL
POSTGRES.FLOAT8=DOUBLE PRECISION
POSTGRES.INTEGER=INTEGER
POSTGRES.NUMERIC=NUMERIC;VARLENGTH=TRUE
POSTGRES.TEXT=VARCHAR;VARLENGTH=TRUE;DEFAULT=255;USEACTUALDATA=TRUE
POSTGRES.TIME=TIME
POSTGRES.TIMESTAMP=TIMESTAMP
POSTGRES.OID=INTEGER
MYSQL.BOOLEAN=SMALLINT
MYSQL.BIT=SMALLINT
MYSQL.TINYBLOB=VARCHAR(255) FOR BIT DATA
MYSQL.BLOB=BLOB;VARLENGTH=TRUE
MYSQL.MEDIUMBLOB=BLOB;VARLENGTH=TRUE
MYSQL.LONGBLOB=BLOB;VARLENGTH=TRUE
MYSQL.CHAR=CHAR;VARLENGTH=TRUE
MYSQL.CHARACTER=CHAR;VARLENGTH=TRUE
MYSQL.DATE=DATE
MYSQL.DATETIME=TIMESTAMP
MYSQL.YEAR=SMALLINT
MYSQL.NUMERIC=NUMERIC;VARLENGTH=TRUE
MYSQL.DECIMAL=NUMERIC;VARLENGTH=TRUE
MYSQL.FLOAT=REAL
MYSQL.DOUBLE=DOUBLE
MYSQL.REAL=DOUBLE
MYSQL.TINYINT=SMALLINT
MYSQL.SMALLINT=SMALLINT
MYSQL.MEDIUMINT=INT
MYSQL.INTEGER=INT
MYSQL.BIGINT=BIGINT
MYSQL.BIT_UNSIGNED=SMALLINT
MYSQL.TINYINT_UNSIGNED=SMALLINT
MYSQL.SMALLINT_UNSIGNED=SMALLINT
MYSQL.MEDIUMINT_UNSIGNED=INT
MYSQL.INTEGER_UNSIGNED=INT
MYSQL.BIGINT_UNSIGNED=BIGINT
MYSQL.DECIMAL_UNSIGNED=NUMERIC;VARLENGTH=TRUE
MYSQL.NUMERIC_UNSIGNED=NUMERIC;VARLENGTH=TRUE
MYSQL.TINYTEXT=VARCHAR;VARLENGTH=TRUE;DEFAULT=255
MYSQL.TEXT=VARCHAR;VARLENGTH=TRUE;DEFAULT=65535
MYSQL.MEDIUMTEXT=CLOB(16M)
MYSQL.LONGTEXT=CLOB(2G)
MYSQL.TIME=TIME
MYSQL.TIMESTAMP=TIMESTAMP
MYSQL.VARCHAR=VARCHAR;VARLENGTH=TRUE;DEFAULT=255
MYSQL.BINARY=CHAR FOR BIT DATA;VARLENGTH=TRUE
MYSQL.VARBINARY=VARCHAR FOR BIT DATA;VARLENGTH=TRUE    

如何在 Windows 或 Linux 上运行这个工具

要使用这个工具,只需要运行两个命令。第一个命令是 geninput.cmd(Windows)和 geninput(Linux)。第二个命令是 unload.cmd(Windows)和 unload(Linux)。这里的示例显示 Linux 上的情况,但是在这两种平台上是一样的。

第一步 —— 生成输入文件

如果没有为 geninput 脚本指定参数,那么显示一个消息,它指出需要指定 MySQL/PostgreSQL 数据库名(如下所示)。重新运行这个脚本并指定 MySQL/PostgreSQL 数据库名;将为给定的数据库生成输入文件。

清单 6. 运行 geninput

db2@db2lab9:~/migr> ./geninput
Usage : geninput dbname
db2@db2lab9:~/migr> ./geninput ama
[2006-05-23 09.35.54.563] dbSourceName:postgres
[2006-05-23 09.35.54.564] db2SchemaName:ama
[2006-05-23 09.35.54.565] server:server.ibm.com
[2006-05-23 09.35.54.565] dbName:ama
[2006-05-23 09.35.54.565] port:5432
[2006-05-23 09.35.54.565] uid:postgres
[2006-05-23 09.35.54.566] INPUT Directory = /home/db2/migr/input
[2006-05-23 09.35.54.575] Configuration file loaded: 'driver.properties'
[2006-05-23 09.35.54.576] Configuration file loaded: 'url.properties'
[2006-05-23 09.35.54.599] Driver org.postgresql.Driver loaded
[2006-05-23 09.35.54.960] ama.ama_addresstype:SELECT * FROM public.ama_addresstype
ama.ama_country_codes:SELECT * FROM public.ama_country_codes
ama.ama_hosp_affil:SELECT * FROM public.ama_hosp_affil
ama.ama_msa:SELECT * FROM public.ama_msa
ama.ama_mti:SELECT * FROM public.ama_mti
ama.ama_pe:SELECT * FROM public.ama_pe
ama.ama_physicians:SELECT * FROM public.ama_physicians
ama.ama_pmsa:SELECT * FROM public.ama_pmsa
ama.ama_schools:SELECT * FROM public.ama_schools
ama.ama_specialties_group:SELECT * FROM public.ama_specialties_group
ama.ama_top:SELECT * FROM public.ama_top
ama.ama_type_of_practice:SELECT * FROM public.ama_type_of_practice
ama.calculation:SELECT * FROM public.calculation
ama.calculation_group:SELECT * FROM public.calculation_group
ama.category:SELECT * FROM public.category
ama.code_lookup:SELECT * FROM public.code_lookup
ama.physician_calculation:SELECT * FROM public.physician_calculation
ama.physician_calculation_group:SELECT * FROM public.physician_calculation_group
ama.physician_category:SELECT * FROM public.physician_category
ama.possible_answer:SELECT * FROM public.possible_answer
ama.question:SELECT * FROM public.question
ama.topic:SELECT * FROM public.topic

输入文件将创建在当前工作目录的 input 目录中。可以修改这个文件来删除不希望迁移的表,方法是删除卸载此数据的 SQL 查询。

第二步 —— 生成 DDL 并卸载数据

现在要运行提取程序,它为 DB2 生成 DDL 并将数据从 MySQL/PostgreSQL 数据库卸载。需要用这个程序的参数指定数据库名。

清单 7. 运行 unload

db2@db2lab9:~/migr> ./unload ama
[2006-05-23 09.40.43.157] TABLES_PROP_FILE:/home/db2/migr/input/ama.tables
[2006-05-23 09.40.43.159] DRIVER_PROP_FILE:driver.properties
[2006-05-23 09.40.43.160] URL_PROP_FILE:url.properties
[2006-05-23 09.40.43.161] DATAMAP_PROP_FILE:datamap.properties
[2006-05-23 09.40.43.162] colsep:~
[2006-05-23 09.40.43.162] dbSourceName:postgres
[2006-05-23 09.40.43.163] threads:5
[2006-05-23 09.40.43.164] server:server.ibm.com
[2006-05-23 09.40.43.165] dbName:ama
[2006-05-23 09.40.43.166] port:5432
[2006-05-23 09.40.43.167] uid:postgres
[2006-05-23 09.40.43.168] fetchSize:100
[2006-05-23 09.40.43.186] Configuration file loaded: '/home/db2/migr/input/ama.tables'
[2006-05-23 09.40.43.188] query size 22 schemaName size = 22
[2006-05-23 09.40.43.387] Configuration file loaded: 'driver.properties'
[2006-05-23 09.40.43.389] Configuration file loaded: 'url.properties'
[2006-05-23 09.40.43.398] Configuration file loaded: 'datamap.properties'
[2006-05-23 09.40.43.414] Driver org.postgresql.Driver loaded
[2006-05-23 09.40.43.606] Starting Blades
[2006-05-23 09.40.43.607] Starting Blade_1
[2006-05-23 09.40.43.613] Starting Blade_0
[2006-05-23 09.40.43.613] Starting Blade_3
[2006-05-23 09.40.43.615] Starting Blade_2
[2006-05-23 09.40.43.615] Starting Blade_4
[2006-05-23 09.40.43.883] Blade_3 unloaded 21 rows in 269 ms for ama.ama_pe
[2006-05-23 09.40.44.218] Blade_4 unloaded 5 rows in 603 ms for ama.ama_addresstype
[2006-05-23 09.40.44.273] Blade_3 unloaded 0 rows in 390 ms for ama.possible_answer
[2006-05-23 09.40.44.560] Blade_1 unloaded 10 rows in 952 ms for ama.ama_top
[2006-05-23 09.40.44.569] Blade_3 unloaded 0 rows in 296 ms for ama.category
[2006-05-23 09.40.44.687] Blade_2 unloaded 0 rows in 1072 ms for ama.physician_calculation
[2006-05-23 09.40.44.718] Blade_4 unloaded 0 rows in 500 ms for ama.question
[2006-05-23 09.40.44.881] Blade_3 unloaded 0 rows in 312 ms for ama.calculation_group
[2006-05-23 09.40.44.914] Blade_2 unloaded 384 rows in 227 ms for ama.ama_pmsa
[2006-05-23 09.40.44.984] Blade_4 unloaded 493 rows in 266 ms for ama.ama_country_codes
[2006-05-23 09.40.45.076] Blade_2 unloaded 13 rows in 162 ms for ama.ama_type_of_practice
[2006-05-23 09.40.45.343] Blade_4 unloaded 201 rows in 359 ms for
ama.ama_specialties_group
[2006-05-23 09.40.45.451] Blade_1 unloaded 7141 rows in 891 ms for ama.ama_hosp_affil
[2006-05-23 09.40.45.691] Blade_0 unloaded 6102 rows in 2078 ms for ama.ama_mti
[2006-05-23 09.40.45.869] Blade_1 unloaded 0 rows in 418 ms for ama.code_lookup
[2006-05-23 09.40.46.024] Blade_0 unloaded 0 rows in 333 ms for ama.calculation
[2006-05-23 09.40.46.236] Blade_0 unloaded 0 rows in 212 ms for
ama.physician_calculation_group
[2006-05-23 09.40.46.380] Blade_0 unloaded 0 rows in 144 ms for ama.physician_category
[2006-05-23 09.40.46.405] Blade_1 unloaded 1863 rows in 536 ms for ama.ama_schools
[2006-05-23 09.40.46.539] Blade_1 unloaded 4 rows in 134 ms for ama.ama_msa
[2006-05-23 09.40.46.917] Blade_0 unloaded 0 rows in 537 ms for ama.topic
[2006-05-23 09.40.48.931] ama_physicians 10000 rows unloaded in 3.835 sec
[2006-05-23 09.40.52.048] ama_physicians 10000 rows unloaded in 3.117 sec
........
[2006-05-23 09.44.21.891] ama_physicians 10000 rows unloaded in 2.152 sec
[2006-05-23 09.44.24.200] ama_physicians 10000 rows unloaded in 2.309 sec
[2006-05-23 09.44.26.670] Blade_2 unloaded 969995 rows in 221594 ms for ama.ama_physicians
[2006-05-23 09.44.26.671] ==== Total time: 223.0 sec
[2006-05-23 09.44.26.923] done Blade_0
[2006-05-23 09.44.27.175] done Blade_1
[2006-05-23 09.44.27.427] done Blade_2
[2006-05-23 09.44.27.679] done Blade_3
[2006-05-23 09.44.27.931] done Blade_4

工具的输出

对数据库成功地运行这个工具之后,进入输出目录(在我们的示例中是 output/ama)查看输出,如下所示:

清单 8. 工具的输出

db2@db2lab9:~/migr> ls -l output/ama
total 76
drwxr-xr-x 2 db2 db2 4096 2006-05-23 06:16 ama_data
-rw-r--r-- 1 db2 db2 1212 2006-05-23 09:44 ama_db2checkpending.sql
-rw-r--r-- 1 db2 db2 2687 2006-05-23 09:44 ama_db2cons.sql
-rw-r--r-- 1 db2 db2  662 2006-05-23 09:44 ama_db2drop.sql
-rw-r--r-- 1 db2 db2 1378 2006-05-23 09:44 ama_db2fkdrop.sql
-rw-r--r-- 1 db2 db2 3523 2006-05-23 09:44 ama_db2fkeys.sql
-rw-r--r-- 1 db2 db2 13190 2006-05-23 09:44 ama_db2load.sql
-rw-r--r-- 1 db2 db2 3148 2006-05-23 09:44 ama_db2runstats.sql
-rw-r--r-- 1 db2 db2 1143 2006-05-23 09:44 ama_db2.sh
-rw-r--r-- 1 db2 db2 1192 2006-05-23 09:44 ama_db2tabcount.sql
-rw-r--r-- 1 db2 db2 7099 2006-05-23 09:44 ama_db2tables.sql
-rw-r--r-- 1 db2 db2 4336 2006-05-23 09:44 ama_db2tabstatus.sql
drwxr-xr-x 2 db2 db2 4096 2006-05-23 06:06 ama_dump
drwxr-xr-x 2 db2 db2 4096 2006-05-23 06:06 ama_msg      

下面的表对生成的每个文件进行解释。

表 9. 输出文件

文件/目录名 说明
ama_data 包含从源数据库卸载的所有数据文件。
ama_dump 包含没有装载到 DB2 中的数据。DB2 LOAD 实用程序将转储没有装载到 DB2 中的数据。
ama_msg 包含 DB2 LOAD 实用程序生成的所有消息。
ama_db2tables.sql 包含 DB2 的表创建脚本。
ama_db2cons.sql 包含所有约束和索引。建议不要对这个工具生成的检查约束进行反向工程。这个文件包含主键、惟一约束和所有索引的 DDL。
ama_db2fkeys.sql 包含所有外键约束。
ama_db2load.sql 包含用来装载数据的 DB2 LOAD 实用程序脚本。
ama_db2tabcount.sql

ama_db2tabstatus.sql

ama_db2fkdrop.sql

ama_db2drop.sql

ama_db2checkpending.sql

包含用来检验数据移动的表行计数。

在 LOAD 实用程序完成之后,检查表的状态。

用来删除所有外键约束。

用来删除 DB2 中的所有表。

在装载数据之后,用来让表离开检查未决状态。

ama_db2.sh

ama_db2.cmd

这个 shell 脚本用于在 Linux 平台上创建所有 DB2 对象。

这个 shell 脚本用于在 Windows 平台上创建所有 DB2 对象。

由于不同的数据库以不同方式实现约束,有几点需要注意:

在 MySQL/PostgreSQL 中,可以在可空列上创建惟一约束或索引,但是 DB2 要求具有惟一约束的列定义为 NOT NULL。

在 MySQL/PostgreSQL 中,即使主键是空的,也可以为主键创建外键。DB2 不允许主键具有空值。

这个工具处理这些差异的方法是,自动生成 DB2 所需的 DDL 并将惟一或主键列定义为 NOT NULL。因此,为了进行迁移,可能需要修改一些数据。

步骤 3:迁移到 DB2

现在,已经可以进行迁移了。已经生成了创建 DB2 对象所需的所有脚本。我们采用一些最佳实践进行迁移,使您的 DB2 体验尽可能轻松。

在 DB2 中创建数据库

可以用 CREATE DB dbname 命令创建 DB2 数据库。在创建 DB2 数据库时,会替您创建三个表空间 —— System、Temporary 和 User。如果使用 DB2 Viper,那么它将创建 USER 表空间,作为使用自动存储的数据库管理的空间(DMS)。DMS 表空间提供最好的性能和大小合适的缓冲池。临时表空间应该创建为系统管理的空间(SMS)。

运行 Autoconfigure 命令进行调整

表 10. 自动配置 DB2 数据库

参数名 说明
mem_percent 希望让 DB2 专用的服务器内存百分比。
workload_type 数据库是用于 OLTP、数据仓库,还是用于这两种目的?如果不确定,就使用 Mixed。
num_stmts 应用程序中一个工作单元中的平均 SQL 语句数量。
tpm 应用程序中每分钟的事务量是多少?
admin_priority 管理的优先次序是什么?是性能优先,还是数据库恢复优先?
is_populated 数据库中是否填充了足够的数据?如果自从上次运行这个工具以来表中的行数发生了显著变化,那么再次运行这个工具。
num_local_apps 数据库服务器上有多少个访问数据库的批量程序?
num_remote_apps 有多少个远程应用程序将连接数据库?如果使用 Tomcat 或 WebSphere 等应用服务器,那么使用池中的连接总数。
isolation 应用程序的隔离是什么?使用 RR,因为它将保守地计算锁内存需求。
bp_resizable 调整过缓冲池吗?如果没有,那么让 DB2 调整缓冲池。

在创建数据库之后,运行 DB2 AUTOCONFIGURE 命令来调整数据库,见 清单 9。回答 10 个问题并对数据库运行这个命令。最好从 Control Center 运行这个命令,因为通过 GUI 运行它非常直观。

对数据库运行 autoconfigure 命令,或者使用 DB2 Control Center 通过 GUI 交互式地运行它。

清单 9. Autoconfigure

$ db2 connect to yourdbname
$ db2 autoconfigure using
  mem_percent   85
  workload_type  simple
  num_stmts    20
  tpm       3000
  admin_priority  performance
  is_populated   yes
  num_local_apps  0
  num_remote_apps 500
  isolation    cs
  bp_resizeable  yes
apply db and dbm;
$ db2 connect reset             

在运行迁移脚本之前,创建表空间和缓冲池

这个工具的输出之一是每个表中最大行长度的估计值。最大行长度将决定表空间的页大小是 4K、8K、16K 还是 32K。通过查看这个文件的输出,决定对于每种大小需要多少个表空间。在创建对象之前,使用 DB2 Control Center 创建这些表空间(采用自动存储)。如果每种页大小都至少有一个表空间,那么将运行所有表创建脚本,因为应该不需要指定在哪个表空间中创建它们。如果想更轻松一点儿,那么创建一个页大小为 32K 的 DMS 表空间和一个 4K 的 DMS 表空间,然后再运行表创建脚本。

如果在 MySQL/PostgreSQL 数据库中使用了 LOBS,那么还需要创建 LARGE 表空间。同样,通过 Control Center 很容易完成这个任务。

在 DB2 数据库中运行迁移脚本

在执行以上步骤之后,运行脚本 <dbname>_db2.sh(Linux)或 <dbname>_db2.cmd(Windows)来创建所有对象并将数据装入 DB2。下面是一个示例脚本:

清单 10. 创建对象并装载数据

#!/bin/bash
if [ "$1" = "" ] ; then
  echo To run this script, specify name of the db2 database
  echo for example, "./ama_db2 sample"
  echo where sample is the name of the db2 database
  echo
  exit 1
fi
OUTPUT=ama_db2.log
echo Executing Script ama_db2.sh > $OUTPUT
echo Connecting to $1
db2 connect to $1 >> $OUTPUT
echo Running ama_db2tables.sql script to create all tables
db2 -tvf ama_db2tables.sql >> $OUTPUT
echo Running ama_db2cons.sql script to create primary keys and indexes
db2 -tvf ama_db2cons.sql >> $OUTPUT
echo Running ama_db2load.sql script to create to load the data
db2 -tvf ama_db2load.sql >> $OUTPUT
echo Running ama_db2fkeys.sql script to create all foreign keys
db2 -tvf ama_db2fkeys.sql >> $OUTPUT
echo Running ama_db2tabcount.sql script to count rows from all tables
db2 -tvf ama_db2tabcount.sql >> $OUTPUT
echo Running ama_db2tabstatus.sql script to show status of tables after load
db2 -tvf ama_db2tabstatus.sql >> $OUTPUT
db2 connect reset >> $OUTPUT
echo
echo Check the log file $OUTFILE for any errors or issues
echo

迁移脚本执行以下任务。

在 DB2 表中创建所有对象。

创建所有主键和索引。

使用 DB2 LOAD 实用程序装载数据。这个实用程序将装载数据并为表中的数据生成统计数据。

装载数据之后,创建外键约束。

统计所有 DB2 表的行数,从而检查数据移动的完整性。

报告在 LOAD 之后表的可用性状态。

如果已经清理了数据,那么迁移应该会很顺利。在创建外键约束时,检查日志文件中记录的错误并在源数据库中纠正它,然后再次尝试迁移。

可能需要用其他脚本执行以下任务:

删除 DB2 中的所有表。

删除所有外键约束。最好在删除表之前删除所有外键约束。

如果迁移过程很顺利,那么可能不需要再次运行 runstats 命令(在进行数据装载时已经运行了),但是可以单独运行它。

在 DB2 数据库中启用自动维护

在成功地迁移到 DB2 之后,强烈建议为数据库启用自动维护。可以通过 Control Center 配置 DB2,让它自动管理备份、runstats 和表重构。需要指定一个维护时间窗,让 DB2 知道可以在什么时候自动执行这些作业。同样,这不是一个作业调度器,但是可以通过 DB2 Task Center 设置维护作业的执行时间。

再次运行 autoconfigure

在迁移数据之后,运行 configuration advisor,让 DB2 根据工作负载进行优化调整。

常见问题

问题: 如何获得这个工具的源代码?

回答: 首先,我们希望了解 bug 和问题。如果您承诺将您做的改进与我们分享,那么我们不介意与您分享代码。如果您希望获得源代码,那么请与作者之一联系。

问题: 我在创建表时遇到了错误。

回答: 可能是缺少具有所需页大小的表空间。创建具有所需页大小的表空间,比如 8K、16K 或 32K。

问题: 我遇到一个错误 Missing data map for ... 而且应用程序退出了。

回答: 一定是忘了在 mapping.properties 文件中添加数据类型。从 JAR 文件中提取出 mapping.properties 文件,添加缺少的数据类型并重新构建 JAR 文件。如果这是一个很严重的问题,请通知作者之一。

问题: 这个工具有什么限制吗?

回答: 这个工具不处理列默认值、检查约束、来自 MySQL/PostgreSQL 的存储过程或函数。

问题: 这个工具处理 PostgreSQL 的序列对象吗?

回答: 这个工具将序列转换为 identity 属性。但是,DB2 允许使用序列对象。

问题: 可以用这个工具迁移其他数据库吗?

回答: 是的,可以。这个工具是一个通用迁移工具,可以迁移具有通用 JDBC 驱动程序的任何数据库。我们对 Oracle 数据库测试过这个工具,效果很好。但是,我们还没有进行足够的测试。这个工具还可以用于 Microsoft SQL Server 和 Sybase。但是,对于将其他数据库迁移到 DB2,建议使用更万能的免费 IBM 工具 Migration Toolkit(也称为 MTK)。请通过 参考资料 下载这个工具。

结束语

在我们开发这个工具时,关注的重点是开发一个内存占用非常少的程序以获得最好的性能,并使用多线程方式来提高迁移的速度。这不是一个很简单的程序,如果您遇到了错误或问题,请让我们知道。我们可能无法满足各种改进需求,但是会非常认真地纠正 bug。

我们不保证这个程序能够满足您的所有需求,所以在开始使用它之前,请仔细阅读 免责声明。

我们的目的是让您开始考虑使用 DB2 这种强大的数据库,直到最近 DB2 仍然主要在大企业中使用。请使用 DB2 Express-C 并利用世界级数据库的优势来满足您的数据库需求。

免责声明

本文包含示例代码。IBM 授予您(“被许可方”)使用该示例代码的非专有的、版权免费的许可证。然而,该示例代码是按原样提供的,任何形式的(不论是明示的,还是默示的)保证,包括对适销性、适用于特定用途或非侵权性的默示保证。IBM 及其许可方不对被许可方因使用该软件而遭受的任何损失负责。任何情况下,无论损失是如何发生的,也不管责任条款怎样,IBM 或其许可方都不对因使用该软件或不能使用该软件所引起的收入的减少、利润的损失或数据的丢失,或者直接的、间接的、特殊的、由此产生的、附带的损失或惩罚性的损失赔偿负责,即使 IBM 已经被明确告知此类损害的可能性,也是如此。

Tags:MySQL PostgreSQL 迁移

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接