Replicating data from SQL Server to BigQuery by DataFusion
Scenario
- 參考官方 Replicating data from SQL Server to BigQuery 進行建立
- 參考 Connect Private Data Fusion instance with a Private Cloud SQL instance using CloudSQL proxy 進行建立

因此需透過 GCE 的 Proxy 進行連線

實做方式
前置需求
啟用 API
- 點我啟用相關 API
API 啟用連結如下
1https://console.cloud.google.com/flows/enableapi?apiid=datafusion.googleapis.com,bigquery.googleapis.com,storage.googleapis.com,sqladmin.googleapis.com建立 VPC
1export PRJ_ID="PROJECT_ID"2export VPC_NAME="NAME"3
4gcloud compute networks create ${VPC_NAME} --project=${PRJ_ID} --subnet-mode=custom --mtu=1460 --bgp-routing-mode=regional5
6gcloud compute networks subnets create ${VPC_NAME}-us --project=${PRJ_ID} --range=10.1.1.0/24 --stack-type=IPV4_ONLY --network=${VPC_NAME} --region=us-central1 --enable-private-ip-google-access7
8gcloud compute --project=${PRJ_ID} firewall-rules create ${VPC_NAME}-allow-rdp --direction=INGRESS --priority=1000 --network=${VPC_NAME} --action=ALLOW --rules=tcp:3389 --source-ranges=0.0.0.0/09
10gcloud compute --project=${PRJ_ID} firewall-rules create ${VPC_NAME}-allow-internal --direction=INGRESS --priority=1000 --network=${VPC_NAME} --action=ALLOW --rules=all --source-ranges=10.0.0.0/8建立 CloudSQL
建立 CloudSQL for MSSQL 並啟用 private ip 後,即可建立測試資料
建立測試資料
- 匯入測試資料
- 需使用 SSMS 工具進行連線至 MSSQL 主機,本範例使用 GCE 進行
- 先建立好一台 Windows Server 2022 主機
- 下載並安裝 SSMS 工具
- 開啟 CDC 同步
匯入測試資料
下載 AdventureWorks2017.bak 檔後匯入資料庫,於 CloudSQL 終點選 import

點選 BROWSE 建立新的 Bucket

輸入 Bucket 名稱

選擇 Region

使用預設,點選繼續

同樣選擇預設

點選建立

點選確認

上傳到 Bucket 後,選擇 bak 檔案

- 選擇上傳至 bucket 的 bak 檔案
- 輸入匯入後建立的資料庫名稱
- 匯入

設定 Authorized network

使用 SSMS 確認
Server name 輸入 CloudSQL ip,內外部 ip 均可 Authentication 選擇 SQL Server Authentication Login 預設帳號為 sqlserver Password 為之前建立密碼

查看是否成功匯入

設定 CDC 同步
參考 Enable change data capture (CDC) 進行設定
啟動資料庫 CDC 同步功能
1EXEC msdb.dbo.gcloudsql_cdc_enable_db [DB_NAME]預期結果

啟用 CDC capture job
1EXEC sys.sp_cdc_start_job @job_type = N'cleanup'
啟用資料表同步
1EXEC sys.sp_cdc_enable_table2 @source_schema = N'dbo',3 @source_name = N'age',4 @role_name = N'CDC'確認是否啟用成功
1EXECUTE sys.sp_cdc_help_change_data_capture2 @source_schema = N'dbo',3 @source_name = N'age'
建立 CloudSQL Proxy VM
由於 DataFusion 無法直接連到 CloudSQL,因此必須透過建立一台 GCE 上面跑 CloudSQL Proxy 方式連線
首先建立一台 Ubuntu 20.04 VM 並依照以下流程安裝 MSSQL Client 套件
Install SQL Server command-line tools on Linux - SQL Server | Microsoft Learn
1curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc2curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list3sudo apt-get update4sudo apt-get install mssql-tools18 unixodbc-dev5echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc6source ~/.bashrc下載 CloudSQL Proxy
1cd /opt2curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.7.2/cloud-sql-proxy.linux.amd643chmod +x cloud-sql-proxy設定開機啟動,記得置換 CloudSQL Connection name
1export INSTANCE_CONNECTION_NAME="YOUR_CONNECTION_NAME"2echo "/opt/cloud-sql-proxy --address 0.0.0.0 --port 1433 ${INSTANCE_CONNECTION_NAME} --private-ip &" > /opt/start_proxy.sh3sed -i '1i #!/bin/sh' /opt/start_proxy.sh4chmod +x /opt/start_proxy.sh5echo "[Unit]6Description=start cloudsql proxy7
8[Service]9ExecStart=/opt/start_proxy.sh10Type=oneshot11RemainAfterExit=yes12
13[Install]14WantedBy=multi-user.target" > /etc/systemd/system/cloudsqlproxy.service15systemctl daemon-reload16systemctl enable cloudsqlproxy.service使用 sqlcmd 測試
1/opt/start_proxy.sh2sqlcmd -S tcp:127.0.0.1,1433 -U YOUR_USERNAME -P YOUR_PASSWORD -C可使用以下指令查詢資料庫
1select DB_NAME()2GO輸出範例

建立 Cloud Data Fusion instance
點我建立 instance

輸入名稱,直接點選 Create 即可

點選 Add to edition

勾選 Enable Private IP

設定 VPC Peering
先至 Data Fusion 中複製必要資訊

- 複製 Project ID
- 複製 Region
- 複製 Instance ID

至 VPC 中新增 PEERING

建立 PEERING
- 輸入名稱
- 選擇其他 PROJECT
- 貼上上一步的 ProjectID
- 貼上上一步步驟 2+3,組成方式為”Region”-“InstanceID”
- 勾選 Export custom routes
- 建立

建立完成後便會出現 PEERING

設定 instance
下載 JDBC 9.4 版本,並解壓縮後,點選 View Instance,如果使用最新版會遇到加密問題而無法連線

點選繼續

點選 Control Center

點選 + 後,再上傳 Driver 上傳

上傳 mssql-jdbc-9.4.1.jre8.jar 檔

Name 輸入 sqlserver
Class name 輸入 com.microsoft.sqlserver.jdbc.SQLServerDriver
Version 維持預設即可

開始同步
回到主選單,點選 Replication

建立 replication job

輸入名稱

- 選擇 SQL Server
- 輸入 CloudSQL Proxy GCE 之 ip
- 選擇前面設定的 driver
- 輸入欲同步的資料庫名稱
- 輸入使用者帳密

點選下一步

- 可設定事先建立好的 Dataset 名稱
- 選擇資料位置
- 下一步

選擇要同步的表格後,再點選下一步

點選下一步

使用預設值,下一步

使用預設值,下一步

點選開始

啟動會需要一點時間

啟動後便可點選 Logs 查看狀況

於 SSMS 資料庫中新增資料

便可於 BQ 中查到所新增之紀錄

疑難排解
資料表無 Primary Key
沒有 Primary Key 會無法正常同步,請留意資料表需有 Primary Key

CloudSQL Proxy VM 無法連線到 CloudSQL
在 CloudSQL Proxy VM 測試連線到 CloudSQL 時發現權限不足
1root@cdc-proxy:/opt# sqlcmd -S tcp:127.0.0.1,1433 -U YOUR_USERNAME -P YOUR_PASSWORD -C2
32023/12/06 03:10:36 [timotion-bigquery:asia-east1:cdc-mssql] accepted connection from 127.0.0.1:5669342023/12/06 03:10:36 [timotion-bigquery:asia-east1:cdc-mssql] failed to connect to instance: failed to get instance: Refresh error: failed to get instance metadata (connection name = "timotion-bigquery:asia-east1:cdc-mssql"): googleapi: Error 403: Request had insufficient authentication scopes.5Details:6[7 {8 "@type": "type.googleapis.com/google.rpc.ErrorInfo",9 "domain": "googleapis.com",10 "metadata": {11 "method": "google.cloud.sql.v1beta4.SqlConnectService.GetConnectSettings",12 "service": "sqladmin.googleapis.com"13 },14 "reason": "ACCESS_TOKEN_SCOPE_INSUFFICIENT"15 }16]17More details:18Reason: insufficientPermissions, Message: Insufficient Permission19Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : Client unable to establish connection because an error was encountered during handshakes before login. Common causes include client attempting to connect to an unsupported version of SQL Server, server too busy to accept new connections or a resource limitation (memory or maximum allowed connections) on the server..20Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : TCP Provider: Error code 0x68.21Sqlcmd: Error: Microsoft ODBC Driver Server : Client unable to establish connection.22Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : Client unable to establish connection due to prelogin failure.如果是使用預設的 GCE service account,會需要調整 access scope,先點選 VM

點選編輯

開啟 CloudSQL 後儲存

並確認是否開啟 sqladmin.googleapis.com 這個 API,如果沒開,使用 sqlcmd 會出現以下錯誤
1Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : Client unable to establish connection because an error was encountered during handshakes before login. Common causes include client attempting to connect to an unsupported version of SQL Server, server too busy to accept new connections or a resource limitation (memory or maximum allowed connections) on the server..2Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : TCP Provider: Error code 0x68.3Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : Client unable to establish connection.4Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : Client unable to establish connection due to prelogin failure.點我開啟 API