http://my.oschina.net/duangr/blog/182216
之前使用的數據庫是MySql,現在要改成PostgreSQL,因此需要將MySql表中數據也遷移過來. 下面是一些具體操作步驟.
前言
之前使用的數據庫是MySql,現在要改成PostgreSQL,因此需要將MySql表中數據也遷移過來. 下面是一些具體操作步驟.
@Author duangr
@Website http://my.oschina.net/duangr/blog/182216
1.相關環境
Host Name | IP | OS | Arch |
duangr-1 | 192.168.56.10 | CentOS 6.4 | x86_64 |
DataBase | Version |
MySql | 5.5.27 |
PostgreSQL | 9.3.1 |
2.數據遷移
我的做法是將數據從MySQL庫中導出到文件中,然后再將文件中的數據導入到PostgreSQL中.
2.1 創建數據文件存儲目錄
1
2
|
# mkdir /tmp/etl
# chmod 777 /tmp/etl
|
解釋下, 我選擇把數據文件放到 /tmp 目錄下,是由於此目錄權限是 777 ,這樣一來MySQL的啟動用戶mysql,以及PostgreSQL的啟動用戶 postgres 都可以讀寫此目錄下面的文件.
(切換成其他目錄均可,但需要保證mysql和postgres用戶都要擁有讀寫權限.)
2.2 從MySQL中導出表數據
以表 tab_duangr 為例,將表中數據導出到文件中
1
2
|
mysql> select * from tab_duangr into outfile "/tmp/etl/tab_duangr.dat" fields terminated by '^A';
Query OK, 792 rows affected (0.01 sec)
|
P.S. 此處使用ASCII字符 0x01 作為文件中字段分隔符,目的是避免與數據字段內容沖突. ^A 需要通過 "Ctrl+V" + "Ctrl+A" 的方式輸入.
2.3 將數據導入到PostgreSQL
需要使用超級用戶登陸PostgreSQL (數據庫為duangr)
1
2
3
4
5
6
7
|
# su - postgres
$ psql -d duangr
psql (9.3.1)
輸入 "help" 來獲取幫助信息.
duangr=# copy tab_duangr from '/tmp/etl/tab_duangr.dat' with delimiter '^A';
COPY 792
|
3. 相關鏈接
我們已對 Django1.6 app完成了數據庫從mysql到PostgreSQL的遷移,如果你的環境很干凈,這個過程就會很簡單,只要允許syncdb 或者 migrate創建表,truncating表中的數據,然后運行dumpdata 和loaddatamanagement命令就完成了。
第一步,在你的PostgreSQL數據庫中創建一個空的實例:
1
|
CREATE DATABASE dbname OWNER rolename;
|
第二步,在你的Django中給創建的數據庫加上配置
在setting.py 中,我們這樣配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
DATABASES = {
'default'
: {
'ENGINE'
:
'django.db.backends.mysql'
,
'NAME'
:
'dbname'
,
'USER'
:
'dbuser'
,
'PASSWORD'
:
'dbpass'
,
'HOST'
:
'mysql.example.com'
,
'PORT'
:
''
,
},
'postgresql'
: {
'ENGINE'
:
'django.db.backends.postgresql_psycopg2'
,
'NAME'
:
'dbname'
,
'USER'
:
'dbuser'
,
'PASSWORD'
:
'dbpass'
,
'HOST'
:
'postgresql.example.com'
,
'PORT'
:
''
,
}
}
|
這樣我們就指定了以后名稱操作的是哪個數據庫。
第三步,在PostgreSQL實例中創建表
1
|
python manage.py syncdb --migrate --no-initial-data --database=postgresql
|
在PostgreSQL中運行syncdb 和 migrations,這個過程並沒有初始數據。
第四步,truncate新創建的表
盡管我們在先前的步驟中指定了 –no-initial-data ,為了防止在遷移過程中用戶的自定義數據在未知情況下加入了表中,我們最好還是truncate一下新建的表,我們可以生成一個SQL腳本,運行:
1
|
python manage.py sqlflush --database=postgresql
|
第五步,從mysql中備份數據到JSON 文件中
Django 有一個dumpdata命令,用它可以生成一個數據庫無關的備份,默認格式是JSON。
1
|
python manage.py dumpdata --all --natural --indent=4 > dbname.json
|
這里的 -all 參數是為了確保你在導出數據的過程中有可能有你自己的過濾和修改數據的需求,-natural 參數告訴Django使用natural keys(如果可用的話) –indent 參數是為了使輸出更加可讀。
你也許想只導出特定的apps里的數據,或者只導出一個celery logs ,這樣的話,你就可以使用 –exclude參數,例如:
1
|
python manage.py dumpdata --all --natural --exclude=djcelery --exclude=search.SearchLog --indent=4 > dbname.json
|
第六步,加載JSON數據到PostgreSQL數據庫中
1
|
python manage.py loaddata dbname.json --database=postgresql
|
基本上遷移的過程就結束了,現在你只要修改一下你的數據庫配置,然后是PostgerSQL成為默認的數據庫。
1
2
3
4
5
6
7
8
9
10
|
DATABASES = {
'default'
: {
'ENGINE'
:
'django.db.backends.postgresql_psycopg2'
,
'NAME'
:
'dbname'
,
'USER'
:
'dbuser'
,
'PASSWORD'
:
'dbpass'
,
'HOST'
:
'postgresql.example.com'
,
'PORT'
:
''
,
}
}
|
在我們的情況下,我們的數據庫不是很干凈,我們的數據庫是給一個PHP的遺留代碼創建的,我們現在還在一步步擺脫它,我們有一些Django之外的數據庫,並且都在被程序使用,為了把這些遷移到PostgreSQL中,我使用了這個工具,過程還是簡單一些。
注意事項
Django 信號
你可能想禁止這些,當一個數據庫記錄創建的時候,你的程序可能就會發送給你的用過郵件,為了不打擾它們,在加載數據的時候,你需要保證它們被禁止了,Here’s one way to handle this 這里我們使用了檢測器保證信號不會別觸發。
約束(像非空,unique 和外鍵)
我們的數據庫遷移過程碰到了很多這種問題,比如一個外鍵約束,但是其他的一個表不存在了,有一下空置的記錄,但是模型定義中不允許,比如復制的過程中存在unique約束,這些都需要手動干預,我必須使用SQL語句清除掉這些,Dumpdata 和loaddata 將會檢測到這些,所以你的數據庫必須是一個干凈的一致的狀態。
主鍵的硬編碼
這很痛苦,因為在我們的測試 suite中,到處都是主鍵的硬編碼,所以很多測試到失敗了,因為使用PostgreSQL 處理的序列的方法和mysql不太一樣,我必須手動修改700多個測試用例,大都是很簡單的修改但是很消耗時間。
原生SQL語句
幸運的是,我們只有一處使用了原生sql語句,有些mysql中的函數在PostgreSQL中不適用,我們只用修改為在PostgreSQl中相同功能的函數就可以了。
大小寫敏感
字符串比較在PostgreSQL中是大小寫敏感的,但是在Mysql中不是,我在遷移非Django數據表過程中也遇到了一些問題,索引創建的時候,命令需要id,但是字段的名字是Id(字母I),我只要重命名為id就可以了。