容易使用、强大而且 免费!这就是人们对 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 使用一种基于线程的体系结构,而 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 服务器进程(mysqld)可以创建许多线程:
- 一个全局线程(每个服务器进程有一个)负责创建和管理每个用户连接线程。
- 为处理每个新的用户连接创建一个线程。
- 每个连接线程还执行身份验证和查询。
- 在 Windows 上,有一个命名管道处理器线程,它针对命名管道连接请求执行与连接线程相同的工作。
- 一个信号线程处理警报并迫使长时间空闲的连接超时。
- 分配一个线程来处理关闭事件。
- 有一些线程在复制期间处理主服务器和从服务器的同步。
- 使用线程处理表刷新、维护任务等等。
MySQL 使用数据缓存、记录缓存、键缓存、表缓存、主机名缓存和特权缓存来缓存和检索服务器进程中所有线程所使用的不同类型的数据。
另外,MySQL 主进程(mysqld)具有用来处理数据库管理活动的线程,比如备份、恢复、并发控制等等。
PostgreSQL 实例(见 图 2)可以管理一个数据库集群。每个数据库有自己的系统编目,INFORMATION_SCHEMA 和 pg_catalog。所有数据库共享 pg_databases
作为公用系统表。每个数据库是一个单独的实体,数据库的集合称为集群。一个 PostgreSQL 实例可以管理一个数据库集群。一台服务器可以运行多个实例。
在逻辑上,PostgreSQL 数据库可以迁移到 DB2 数据库。这两种数据库都支持模式对象类型。不能从命名的连接访问其他数据库。
PostgreSQL 和 DB2 之间最显著的差异与表空间相关。PostgreSQL 表空间可以跨越多个数据库,而 DB2 表空间特定于一个数据库。
图 2. PostgreSQL 体系结构和进程概况
PostgreSQL 会话由几个主进程组成:
- postmaster 进程是一个主管进程,它生成其他进程并监听用户连接。
- 用户进程(比如 psql)用来处理交互式 SQL 查询。
- postmaster 生成一个或多个名为 postgres 的服务器进程来处理用户的数据请求。
- 服务器进程通过信号量和共享内存来相互通信。
图 3 显示 DB2 的体系结构。这张图解释了 DB2 如何使用缓冲池在磁盘之间处理数据(文件、原始设备、目录等等)。DB2 使用一个连接集中器来处理大量连接。DB2 页清理器和预获取器异步地工作,各个进程单独处理重做日志活动。关于 DB2 中锁和进程的工作方式的详细描述,请参见 参考资料。
图 3. DB2 体系结构和进程概况
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 数据库管理器(实例)和数据库共享内存体系结构
表 1 对比了 MySQL、PostgreSQL 和 DB2 特性。这不是一个完整的列表,但是对比了最常用的特性。
表 1. MySQL、PostgreSQL 和 DB2 特性对比
特性 | MySQL | PostgreSQL | DB2 |
---|---|---|---|
实例 | 通过执行 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 数据类型的定义和差异。表 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。 |
|
下面两个表描述 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 的过程。
|
|
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 上的默认用户 id 是
- 在安装期间,创建默认的实例:
- 在 Windows 上,它称为 DB2。
- 在 Linux 上,它称为 db2inst1。
在默认情况下,DB2 服务器被配置为使用 TCPIP(端口 50000)。可以使用 protocols 按钮修改这个设置。
在安装之后,First Steps 将启动,可以用来帮助创建第一个数据库,这个数据库称为 SAMPLE。
可以从 参考资料 下载 DB2 Express / Express-C。
|
如果要从远程机器连接到 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 中创建的表作为定制查询的结果。
运行第一个组件的脚本是 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%/bin/java -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 |
卸载数据并为 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%/bin/java -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 属性文件来读取 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 |
要使用这个工具,只需要运行两个命令。第一个命令是 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。因此,为了进行迁移,可能需要修改一些数据。
|
|
现在,已经可以进行迁移了。已经生成了创建 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 并利用世界级数据库的优势来满足您的数据库需求。