DataStage序列文章
DataStage 一、安裝
DataStage 二、InfoSphere Information Server進程的啟動和停止
DataStage 三、配置ODBC
DataStage 錯誤集(持續更新)
DataStage 四和五因為包含大量圖片發布不便,有興趣學習和研究者請聯系索要!!!
DataStage 六、安裝和部署集群環境
DataStage 七、在DS中使用配置文件分配資源
DataStage 八、清除日志
說明
默認情況下datastage 9.1版本中只支持Enterprise or Commercial版本的MySQL數據庫,如果要使用MySQL Community版本數據庫則可以通過安裝和配置mysql-connector-odbc驅動來完成;以下的實驗以datastage 9.1.0、MySQL Community 5.0.67 Edition和mysql驅動mysql-connector-odbc-5.3.4-1.el6.x86_64.rpm在Linux上實驗為例。
1 安裝MySQL ODBC驅動
在網上下載mysql-connector-odbc-5.3.4-1版本驅動,然后安裝;
#rpm -ivh mysql-connector-odbc-5.3.4-1.el6.x86_64.rpm
Preparing... ########################################### [100%]
1:mysql-connector-odbc ########################################### [100%]
Success: Usage count is 1
Success: Usage count is 1
安裝結束后得到如下目錄和文件信息
/usr/share/doc/mysql-connector-odbc-5.3.4
/usr/share/mysql
/usr/lib64/mysql
/usr/lib64/mysql/libmysqlclient.so.16.0.0
/usr/lib64/mysql/libmysqlclient.so.16
/usr/lib64/mysql/libmysqlclient_r.so.16.0.0
/usr/lib64/mysql/libmysqlclient_r.so.16
/usr/lib64/libmyodbc5w.so
/usr/lib64/libmyodbc5a.so
/usr/bin/myodbc-installer
libmyodbc5w.so就是我們要用到的驅動文件。
2 配置ODBC
編輯$DSHOME/.odbc.ini文件,根據里面的示例創建mysql odbc;
[odbc_mysql]
Driver=/usr/lib64/libmyodbc5w.so
DriverUnicodeType=1
Description=DataDirect 7.0 MySQL Wire Protocol
Database=mysql
Server=150.18.44.99
User=root
Password=
Port=3306
QueryTimeout=0
ReportCodepageConversionErrors=0
TreatBinaryAsChar=0
TrustStore=
TrustStorePassword=
ValidateServerCertificate=1
Option=3
這里Driver指定新安裝的驅動文件;
DriverUnicodeType指定字節長度,默認情況下datastage使用附帶的DataDirect ODBC管理驅動和支持多種常用的數據庫,但當使用第三方驅動時,第三方驅動與DataDirect ODBC可能不完全兼容,比如一般情況下ds DataDirect ODBC驅動使用4個字節長度的字符(比如UTF16),而第三方驅動使用2個字節長度的字符,這時如果不指定DriverUnicodeType則會發生Unicode converter buffer overflow錯誤;所以當在Driver下面設置了DriverUnicodeType屬性時,DataDirect ODBC管理和維護統一的字節長度;
Server 指定服務器,不要弄錯了,.odbc.ini文件中的示例是HostName;
Port指定端口;
接着將ODBC配置到項目目錄下的uvodbc.config 文件中;
<odbc_mysql>
DBMSTYPE = ODBC
完成這些操作后再通過dssh測試odbc;
#dssh
DataStage Command Language 9.1 Licensed Materials - Property of IBM
(c) Copyright IBM Corp. 1997, 2012 All Rights Reserved.
dscluster logged on: Thursday, November 19, 2015 20:52
>logto dscluster
>ds_connect odbc_mysql
odbc_mysql> show tables;
Tables_in_mysql
---------------
char_test
columns_priv
db
func
help_category
help_keyword
help_relation
help_topic
host
3 亂碼的產生
在一個字符集為AMERICAN_AMERICA.AL32UTF8的Oracle數據庫中建立一張表並存入中文的數據;
create table char_test(
col1 varchar2(300),
col2 varchar2(50)
);
insert into char_test(col1,col2) values('曹操','三國演義中的武王');
insert into char_test(col1,col2) values('劉備','三國演義中的蜀王');
insert into char_test(col1,col2) values('諸葛亮','三國演義中的軍師');
在MySQL數據庫中建立相同的數據表;
create table char_test(
col1 varchar(300),
col2 varchar(50)
);
創建ds job完成oracle到mysql的數據交換;
數據交換完成后發現MySQL數據表中全是亂碼;
mysql> select * from char_test;
+------+----------+
| col1 | col2 |
+------+----------+
| ?? | ???????? |
| ?? | ???????? |
| ??? | ???????? |
+------+----------+
4 亂碼分析
根據MySQL文檔得知,MySQL數據庫可以在數據庫層面、數據表層面、數據表列層面設置字符集,並且它們的設置都繼承於上一級,所以如果在創建表時,沒有為列指定字符集,則列繼承於表的字符集;如果沒有為表指定字符集,則表繼承數據庫的字符集。當客戶端向服務端發送請求時字符將產生這樣的轉換過程(character_set_client(客戶端來源數據使用的字符集)、character_set_connection(連接層字符集)、character_set_results(查詢結果字符集)),so 根據這些來判斷,首先想到的是MySQL數據庫層面使用的字符集和字符序;
mysql> show variables like 'character%';
+--------------------------+--------------------------------------+
| Variable_name | Value |
+--------------------------+--------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | D:\develope\MySQL5.0\share\charsets\ |
+--------------------------+--------------------------------------+
mysql> show variables like 'collation%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | utf8_general_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
此時數據庫使用的字符集和字符序都是latin1,而在創建表時均未指定列和表使用的字符集,所以數據表和數據表列都繼承了數據庫的字符集;
mysql> show table status like 'char_test';
+-----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+-----
----------------+-------------+------------+-------------------+----------+----------------+----------------------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Crea
te_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment |
+-----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+-----
----------------+-------------+------------+-------------------+----------+----------------+----------------------+
| char_test | InnoDB | 10 | Compact | 0 | 0 | 16384 | 0 | 0 | 0 | NULL | 2015
-11-20 10:59:49 | NULL | NULL | latin1_swedish_ci | NULL | | InnoDB free: 9216 kB |
+-----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+-----
----------------+-------------+------------+-------------------+----------+----------------+----------------------+
1 row in set (0.00 sec)
mysql> show full columns from char_test;
+-------+--------------+-------------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+-------+--------------+-------------------+------+-----+---------+-------+---------------------------------+---------+
| col1 | varchar(300) | latin1_swedish_ci | YES | | NULL | | select,insert,update,references | |
| col2 | varchar(50) | latin1_swedish_ci | YES | | NULL | | select,insert,update,references | |
+-------+--------------+-------------------+------+-----+---------+-------+---------------------------------+---------+
所以當客戶端插入中文字符時,MySQL數據庫做了如下轉換:
utf8=>utf8=>latin1
原始數據中含有的(\u0000 ~ \u00ff)范圍以外的Unicode字符會因為無法在latin1字符集中表示而被轉換為"?"(0x3f)符號,以后查詢不管連接字符集如何設置都無法恢復其原始內容。
5 亂碼的解決方法
在分析了數據庫字符集和亂碼原因后知道了亂碼的產生的真正原因了,那如何處理呢?抱着這些問題我做了三種可行的設想和解決方法:
1. 將表的字符集從latin1轉換為utf8;
2. 將數據庫默認字符設置為utf8;
3. 創建數據庫時明確指定字符集;
5.1 將表的字符集從latin1轉換為utf8
這種實現方案主要是為了不影響系統運行和其它用戶並且生產迫切急需的情況下進行的,相對來說它的影響最小,速度快。
alter table char_test default character set=utf8;
alter table char_test convert to character set utf8;
注意:命令1是把表的默認字符設置為utf8(不包括列哦),命令2是把表轉換為utf8(包括列哦)
mysql> show table status like 'char_test';
+-----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+-----
----------------+-------------+------------+-----------------+----------+----------------+----------------------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Crea
te_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment |
+-----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+-----
----------------+-------------+------------+-----------------+----------+----------------+----------------------+
| char_test | InnoDB | 10 | Compact | 3 | 5461 | 16384 | 0 | 0 | 0 | NULL | 2015
-11-20 10:59:49 | NULL | NULL | utf8_general_ci | NULL | | InnoDB free: 9216 kB |
+-----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+-----
mysql> show full columns from char_test;
+-------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+-------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| col1 | varchar(300) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
| col2 | varchar(50) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
+-------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
mysql> truncate table char_test;
Query OK, 3 rows affected (0.05 sec)
此時再重新交換數據,數據就正確了。
mysql> set names gbk;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from char_test;
+--------+------------------+
| col1 | col2 |
+--------+------------------+
| 劉備 | 三國演義中的蜀王 |
| 曹操 | 三國演義中的武王 |
| 諸葛亮 | 三國演義中的軍師 |
+--------+------------------+
3 rows in set (0.01 sec)
注意:如果你使用一些客戶端工具,比如MySQL-Front,連接數據庫時要選擇好字符集,如果沒有選擇默認是數據庫設定的字符集,本文中數據庫默認字符集是latin1,如果你沒有手動選擇為utf8,當查詢如上實驗表是又發生了utf8=>latin1,查詢出來的結果肯定是亂碼。
5.2 將數據庫默認字符設置為utf8
這是一種長遠考慮,比較安全,比較適合開發環境的方案,因為隨着項目規模的擴大,人員的增退因素,不可能每建一個表都要去考慮字符集因素。但缺點就是它必須重啟MySQL服務,並影響系統的運行。
編輯my.ini文件,修改如下的屬性值為utf8;
[client]
port=3306
default-character-set=utf8
[mysql]
default-character-set=utf8
# The default character set that will be used when a new schema or table is
# created and no character set is defined
default-character-set=utf8
注意:每個MySQL版本的字符集設置都不一樣,詳細信息請查閱版本文檔。
然后重啟MySQL服務;服務啟動完成后進一步檢查數據庫字符集信息;
mysql> show variables like 'character%';
+--------------------------+--------------------------------------+
| Variable_name | Value |
+--------------------------+--------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | D:\develope\MySQL5.0\share\charsets\ |
+--------------------------+--------------------------------------+
mysql> show variables like 'coll%';
+----------------------+-----------------+
| Variable_name | Value |
+----------------------+-----------------+
| collation_connection | utf8_general_ci |
| collation_database | utf8_general_ci |
| collation_server | utf8_general_ci |
+----------------------+-----------------+
都為utf8了,根據上面的分析,如果此時創建表沒有知道字符集,那么表和列的字符集都會繼承數據庫字符集;
drop table char_test;
create table char_test(
col1 varchar(300),
col2 varchar(50)
);
mysql> show table status like 'char_test';
+-----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+-----
----------------+-------------+------------+-----------------+----------+----------------+----------------------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Crea
te_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment |
+-----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+-----
----------------+-------------+------------+-----------------+----------+----------------+----------------------+
| char_test | InnoDB | 10 | Compact | 0 | 0 | 16384 | 0 | 0 | 0 | NULL | 2015
-11-20 10:59:49 | NULL | NULL | utf8_general_ci | NULL | | InnoDB free: 9216 kB |
+-----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+-----
----------------+-------------+------------+-----------------+----------+----------------+----------------------+
1 row in set (0.00 sec)
mysql> show full columns from char_test;
+-------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+-------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| col1 | varchar(300) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
| col2 | varchar(50) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
+-------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
2 rows in set (0.00 sec)
沒錯吧!此時再交換數據也不會亂碼了。
mysql> select * from char_test;
+--------+------------------+
| col1 | col2 |
+--------+------------------+
| 劉備 | 三國演義中的蜀王 |
| 曹操 | 三國演義中的武王 |
| 諸葛亮 | 三國演義中的軍師 |
+--------+------------------+
5.3 創建數據庫時明確指定字符集
這種方案適用於早期數據庫規划階段和當數據庫需要經常遷移時使用;
create database sydb default character set utf8 collate utf8_general_ci;
mysql> use sydb
Database changed
mysql> show variables like 'character%';
+--------------------------+--------------------------------------+
| Variable_name | Value |
+--------------------------+--------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | D:\develope\MySQL5.0\share\charsets\ |
+--------------------------+--------------------------------------+
8 rows in set (0.00 sec)
6 總結
亂碼是數據庫和數據交換中常見的問題之一,導致的原因很多,有字符集不一致的、有字符集不兼容的、有轉換出錯的、有應用程序導致的等;Oracle在創建數據庫時使用character set 參數定義數據庫的字符集,客戶端中使用NLS_LANG變量定義客戶端環境的字符集,當客戶端和服務端的字符集不一樣時,服務端先執行字符集轉換,然后在存儲數據;MySQL中字符集設置相對比較靈活,可以在數據庫層面、數據表層面和數據表列層面設置,大大提高了數據表字符集擴展和管理。雖然每個數據庫對字符的處理方式也不盡相同,但總的思想是相同的,字符集也是遵循標准或一定規則的,所以閱讀官方文檔了解原理和基礎知識是一切的開始。
--The end(2015-11-20)