首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

SQL Server 遷移 MySQL 實戰對比:DTS 直連 vs 腳本 ETL (PHP/ASP) 兩種方案優劣深度剖析

     編輯:MySQL 資料庫相關知識

方案一:MySQL ODBC + SQL Server DTS 直連遷移 (圖形化、免代碼)

操作流程

  1. 安裝 MySQL Connector/ODBC,配置系統 DSN (如 testMySQL)
  2. SQL Server 企業管理器 → 右鍵庫 → **所有任務 → 匯出資料**
  3. 來源:SQL Server;目的地:**Microsoft OLE DB Provider for ODBC Drivers** → 選 testMySQL
  4. 選擇「複製表和視圖」或「寫入查詢結果」
  5. 執行,查看成功/失敗統計

致命缺陷 (作者實測)

問題根因影響
ntext/image 類型無法寫入ODBC 驅動/目標表類型不支援大文本/二進制數據全軍覆沒
時間類型衝突目標表設計用 INT 存 Unix 時間戳,源為 DATETIME導入報錯或數據錯誤
目標表類型自動映射不準DTS 類型推斷邏輯固化VARCHAR(8000) 變 TEXT、精度丟失等
無法控制批次/事務/錯誤重試黑盒過程大表失敗無法斷點續傳

**作者結論**:「此種方法我覺得不能提倡。」

方案二:腳本 ETL (PHP/ASP) — 完全可控、靈活、可驗證

核心優勢

  • **字段級映射控制**:每個列源→目標、類型轉換、清洗邏輯全在代碼中
  • **複雜類型處理**:ntext→VARCHAR(4000)、image→文件系統+路徑存庫、DATETIME→Unix Timestamp (INT)
  • **錯誤隔離與重試**:單行失敗記錄、跳過、重試、不影響整體
  • **進度可觀測**:日誌、計數器、耗時統計
  • **增量同步支援**:配合 WHERE updated_at > last_sync 實現增量

PHP 實現範例 (核心邏輯)

$cnx = odbc_connect('web', 'admin', '123456');  // SQL Server DSN
$cur = odbc_exec($cnx, 'SELECT * FROM user');
$conn = mysql_pconnect('localhost', 'root', '123456');
mysql_select_db('mydb', $conn);

while (odbc_fetch_row($cur)) {
    $f1 = odbc_result($cur, 1);  // id
    $f2 = odbc_result($cur, 2);  // name
    $f3 = odbc_result($cur, 3);  // username
    $f4 = odbc_result($cur, 4);  // password
    $f5 = odbc_result($cur, 5);  // recdate (DATETIME)
    $f5 = timetoint($f5);        // → Unix Timestamp INT
    
    $sql = "INSERT INTO user (id,name,username,password,recdate) 
            VALUES ('$f1','$f2','$f3','$f4','$f5')";
    mysql_query($sql, $conn);
}

function timetoint($str) {
    list($date, $time) = explode(' ', $str);
    list($y,$m,$d) = explode('-', $date);
    list($h,$i,$s) = explode(':', $time);
    return mktime($h,$i,$s,$m,$d,$y);
}

ASP 實現範例 (含類型轉換技巧)

Set conn = Server.CreateObject("ADODB.Connection")
conn.Open "web", "admin", "123456"  ' SQL Server DSN

' 關鍵:SQL 層面直接轉 Unix Timestamp,避免應用層循環轉換
sql = "SELECT ID, name, username, password, 
       DATEDIFF(s, '1970-01-01 00:00:00', recdate) - 8*3600 AS uts,
       reid, filename, fileContentType, filevalue 
       FROM senddate"

Set rs = conn.Execute(sql)
Set conn1 = Server.CreateObject("ADODB.Connection")
conn1.Open "myoa", "root", "q1-d6=7?"

Do While Not rs.EOF
    f1 = rs(0): f2 = rs(1): f3 = rs(2): f4 = rs(3): f5 = rs(4)  ' uts 已是 INT
    sql1 = "INSERT INTO user (ID,name,username,password,recdate) VALUES (" & f1 & ",'" & f2 & "','" & f3 & "','" & f4 & "'," & f5 & ")"
    conn1.Execute sql1
    rs.MoveNext
Loop
' ... 關閉連接清理

疑難雜症處理:ntext/image 類型

  • 方案 A:源庫修改 ntext → NVARCHAR(4000) (實際長度 < 4000),無損遷移
  • 方案 B:image → 文件系統 (ASP 函數 makeattach)
    • 讀取二進制流 (ADODB.Stream Type=1 Binary)
    • 按 Content-Type 判斷副檔名 (.doc/.xls/.jpg/.zip...)
    • 寫入磁盤 D:\attach\attech{ID}.{ext}
    • 數據庫存相對路徑/文件名

方案對比總結

維度DTS + ODBC腳本 ETL (PHP/ASP)
開發成本零 (配置)中 (編寫/調試腳本)
類型映射控制無 (黑盒)完全可控
複雜類型支援極弱極強 (自定義邏輯)
錯誤處理/重試全量失敗/重來行級隔離、斷點續傳
增量同步困難原生支援 (WHERE 條件)
性能 (大表)一般 (單線程)可優化 (批次/並行/禁用索引)
可審計/驗證難代碼即文檔、行數/Checksum 統計
適用場景表少、類型簡單、一次性小遷移生產級、複雜類型、增量、長期同步

現代化 ETL 最佳實踐 (超越 PHP/ASP)

  • Python + SQLAlchemy + PyODBC + MySqlConnector:ORM 映射、批次 executemany、異步並行、進度條
  • Airflow / Prefect / Dagster**:調度、重試、血統、監控、回填
  • Debezium CDC + Kafka**:實時 Binlog 捕獲、無侵入、多下游分發
  • dbt**:轉換層 SQL 管理、測試、文檔、血統
  • DataX / SeaTunnel / Flink CDC**:企業級異構同步平台、插件化、Exactly-Once

結語

**DTS 適合「驗證可行性」,腳本 ETL 適合「生產交付」**。作者 2003 年的親身踩坑 (ntext/image/時間戳/類型映射) 至今仍是異構遷移的**通用痛點**。現代工程應確立:**遷移即代碼、代碼即文檔、文檔即驗證、驗證可自動化**,用成熟 ETL 框架替代手工腳本,將遷移從「藝術」變為「標準化工程」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved