容易使用、強大而且免費!這就是人們對 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 服務器進程(MySQLd)可以創建許多線程:
一個全局線程(每個服務器進程有一個)負責創建和管理每個用戶連接線程。
為處理每個新的用戶連接創建一個線程。
每個連接線程還執行身份驗證和查詢。
在 Windows 上,有一個命名管道處理器線程,它針對命名管道連接請求執行與連接線程相同的工作。
一個信號線程處理警報並迫使長時間空閒的連接超時。
分配一個線程來處理關閉事件。
有一些線程在復制期間處理主服務器和從服務器的同步。
使用線程處理表刷新、維護任務等等。
MySQL 使用數據緩存、記錄緩存、鍵緩存、表緩存、主機名緩存和特權緩存來緩存和檢索服務器進程中所有線程所使用的不同類型的數據。
另外,MySQL 主進程(MySQLd)具有用來處理數據庫管理活動的線程,比如備份、恢復、並發控制等等。
PostgreSQL
PostgreSQL 實例(見 圖 2)可以管理一個數據庫集群。每個數據庫有自己的系統編目,INFORMATION_SCHEMA 和 pg_catalog。所有數據庫共享 pg_databases 作為公用系統表。每個數據庫是一個單獨的實體,數據庫的集合稱為集群。一個 PostgreSQL 實例可以管理一個數據庫集群。一台服務器可以運行多個實例。
在邏輯上,PostgreSQL 數據庫可以遷移到 DB2 數據庫。這兩種數據庫都支持模式對象類型。不能從命名的連接訪問其他數據庫。
PostgreSQL 和 DB2 之間最顯著的差異與表空間相關。PostgreSQL 表空間可以跨越多個數據庫,而 DB2 表空間特定於一個數據庫。
圖 2. PostgreSQL 體系結構和進程概況
PostgreSQL 會話由幾個主進程組成:
postmaster 進程是一個主管進程,它生成其他進程並監聽用戶連接。
用戶進程(比如 psql)用來處理交互式 SQL 查詢。
postmaster 生成一個或多個名為 postgres 的服務器進程來處理用戶的數據請求。
服務器進程通過信號量和共享內存來相互通信。
DB2
圖 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 存儲固定長度的二進制值。 CLOBCLOB(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 字節的存儲空間。 DOUBLEDOUBLE 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 字節的存儲空間。 INTINTEGER
存儲有符號或無符號整數,使用 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 屬性不允許負數。 DOUBLEREAL
存儲雙精度浮點數,限制由硬件決定。雙精度浮點數精確到大約 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 _ DOUBLEREAL
DOUBLE _ SMALLINT SMALLINT 使用檢查約束限制值小於 256。 SMALLINT SMALLINT _ MEDIUMINT INTEGER 如果需要,使用檢查約束限制最大長度。 INTEGER INTEGERINT
_ 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 或更高。 FLOAT4REAL
存儲浮點數,精度為 8 或更低和 6 個小數位。 FLOAT8DOUBLE PRECISION
存儲浮點數,精度為 16 或更低和 15 個小數位。 SMALLINT 存儲有符號或無符號 2 字節整數。 INTEGER 存儲有符號或無符號 4 字節整數。 INT8BIGINT
存儲有符號或無符號 8 字節整數。 SERIALSERIAL4
存儲自動遞增的惟一整數值,最多 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。 FLOAT4REAL
REAL 可以使用 NUMERIC 或 FLOAT。 FLOAT8DOUBLE PRECISION
DOUBLE PRECISION 對於大數值使用 DOUBLE PRECISION,如果精度小於 31,那麼使用 NUMERIC。 SMALLINT SMALLINT _ INTEGER INTEGER _ INT8BIGINT
BIGINT _ VARCHAR(n)CHARACTER VARYING(n)
CHARACTER VARYING
VARCHAR(n) 如果 ‘n’ 小於等於 32K。DB2 要求指定 ‘n’,而 PostgreSQL 不要求指定 ‘n’ 的值。 SERIALSERIAL4
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.shama_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 已經被明確告知此類損害的可能性,也是如此。