在 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 體驗儘可能輕鬆。
在 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 根據工作負載進行優化調整。