SQLServer資料實時同步至PostgreSQL


前言:

為迎合工作需求有時候傳送的資料儲存在SQLServer中但由於工作需要需要儲存到PostgreSQL中進行處理,本文主要通過在SQLServer中設定觸發器和儲存過程的方式完成資料的同步

系統環境說明

軟體 版本 說明
SQLServer 2008R2_X64 X64位
PostgreSQL 9.5_X64
odbc 9.5_X64

postgre_odbc下載安裝

odbc主要是讓PostgreSQL與SQLServer之間建立橋樑利於資料傳輸下載地址

PostgreSQL_odbc選擇要下載的版本

演示環境下載的9.5版本隨本機安裝Postgre資料庫

下載完成解壓得到Psqlodbc_x64.msi,雙擊執行安裝預設即可

安裝完成後通過系統自帶的ODBC資料來源配置系統DNS

點選新增開啟需要新增的資料來源,這裡選擇PostgreSQL ANSIx64

新增PostgreSQL連線

DataSource:連線名稱 ,後續在SQLServer中會用到

Database: 要連線的資料庫

Server: Posgresql服務地址,也可以是IP

Port: 服務埠號

User Name:使用者登入名

Password:登入密碼

輸入連線引數後點擊Test 測試是否成功 成功後點擊Save 儲存即可

新增連結伺服器方法1——用操作介面新增

  1. SQLServer中新增伺服器物件

    開啟SQLServer資料庫連線,找到伺服器物件->連結伺服器->滑鼠右鍵選擇新建連結伺服器

常規

1.設定連線物件名稱

2.選擇訪問介面,這裡先連線本地所以選擇如圖,當新增ODBC時會有所不同

3.輸入產品名稱,這裡隨意填寫(不能為null),測試單詞中有空格新增失敗

4.資料來源名稱,這裡為SQL Server伺服器連線IP,本地連線故以“.”代替

安全性

當切換到安全性選項卡時,預設

  • [x] 不使用安全上下文連線(N)

這裡切換到 使用此安全上下文建立連線 使用SQLServer登入使用者名稱登陸即可

伺服器選項

將RPC 設定為 True 預設為False

將RPC Out 設定為 True 預設為False

將為RPC 啟動針對分散式事務升級 設定為 false 預設為 true

設定完成後單擊確定即可完成設定

新增PostgreSQL 連線伺服器

新增PostgreSQL 連結伺服器與 SQLServer 步驟類似

區別在於:

訪問介面-> Microsoft OLE DB Provider for ODBC Drivers

資料來源 -> 為ODBC連結物件DataSource 名稱

安全性輸入填寫 PostgreSQL 的登陸賬號、密碼即可

伺服器選項相同

新增連結伺服器方法2————用T-SQL命令新增

use master
go
/****** Object: LinkedServer [LOCALHOSTSQL]
判斷是否存在 LOCALHOSTSQL 名稱的LinkedServer 如果有則刪除
******/
IF EXISTS (SELECT srv.name FROM sys.servers srv WHERE srv.server_id != 0 AND srv.name = N'LOCALHOSTSQL')EXEC master.dbo.sp_dropserver @server=N'LOCALHOSTSQL', @droplogins='droplogins'
GO
/****** Object: LinkedServer [LOCALHOSTSQL]
新增本地連結 呼叫儲存過程 master.dbo.sp_addlinkedserver
******/
EXEC master.dbo.sp_addlinkedserver
@server = N'LOCALHOSTSQL', --連結伺服器
@srvproduct=N'SQlServer', --產品名稱
@provider=N'SQLNCLI', --訪問介面
@datasrc=N'.\SQL08R2' --資料來源
/*
安全性新增 呼叫儲存過程 master.dbo.sp_addlinkedsrvlogin
*/
EXEC master.dbo.sp_addlinkedsrvlogin
@rmtsrvname=N'LOCALHOSTSQL', --連結伺服器
@useself=N'False', --
@locallogin=NULL, --本地登陸
@rmtuser=N'sa', --遠端登陸使用者
@rmtpassword='########' --遠端登陸密碼 改成實際使用者名稱密碼
GO
/*
伺服器選項 呼叫儲存過程 master.dbo.sp_serveroption 這裡伺服器選項操作很多,這裡只選擇需要的配置,其他為預設選項
*/
EXEC master.dbo.sp_serveroption
@server=N'LOCALHOSTSQL', --連結伺服器
@optname=N'rpc out', --操作 rpc out選項
@optvalue=N'true' --選項值
GO
EXEC master.dbo.sp_serveroption
@server=N'LOCALHOSTSQL', --連結伺服器
@optname=N'rpc', --操作rpc選項
@optvalue=N'true' --選項值
GO
EXEC master.dbo.sp_serveroption
@server=N'LOCALHOSTSQL',
@optname=N'remote proc transaction promotion', --rpc 事務選項
@optvalue=N'false' GO
/*
判斷是否有 名稱為 POSTGRESQL 的連結伺服器 如果有則刪除
*/
IF EXISTS (SELECT srv.name FROM sys.servers srv WHERE srv.server_id != 0 AND srv.name = N'POSTGRESQL')EXEC master.dbo.sp_dropserver @server=N'POSTGRESQL', @droplogins='droplogins'
GO
/****** 常規 ******/
EXEC master.dbo.sp_addlinkedserver
@server = N'POSTGRESQL', --連結伺服器
@srvproduct=N'PostgreSQL', --產品名稱
@provider=N'MSDASQL', --驅動
@datasrc=N'PostgreSQL95' --資料來源
/* POSTGRESQL 安全性配置 */
EXEC master.dbo.sp_addlinkedsrvlogin
@rmtsrvname=N'POSTGRESQL', --連結伺服器
@useself=N'False', --
@locallogin=NULL, --本地登陸
@rmtuser=N'postgres', --登陸賬號
@rmtpassword='########' --登陸密碼 改為實際密碼 GO
/*伺服器選項*/
EXEC master.dbo.sp_serveroption
@server=N'POSTGRESQL', --連結伺服器
@optname=N'rpc out', --操作選項
@optvalue=N'true' --選項值
GO
EXEC master.dbo.sp_serveroption
@server=N'POSTGRESQL', --連結伺服器
@optname=N'rpc', --操作選項
@optvalue=N'true' --選項值
GO
EXEC master.dbo.sp_serveroption
@server=N'POSTGRESQL',
@optname=N'remote proc transaction promotion',
@optvalue=N'false'
GO

利用T-SQL新增資料來源 連結伺服器名稱可小寫 大小寫混合,利用視窗新增 連結伺服器名稱預設大寫。未找到更好相容解決方案 ,看個人習慣選擇即可

檢查連結伺服器是否正常顯示資料來源,展開剛新增的資料來源物件,檢視目錄下是否有連結資料庫名稱

準備測試資料結構

在SQLServer Books資料庫中新建書單資訊表、並新增測試資料

use Books
go
--判斷是否有存在表
if OBJECT_ID('dbo.books','U') is not null drop table dbo.books
go
--建立表儲存
create table books(
id int identity(1,1) primary key,
name varchar(150) not null,
price float not null,
stock int not null
)
go
--新增資料
insert into books(name,price,stock)values
('Access入門實戰',49.5,999),
('T-SQL效能調優祕笈',49.0,999),
('.NET MVC5 高階變成',79.8,999),
('Python 入門實戰',89.00,999);
--檢查新增資料
select * from books;

postgreSQL中新增同結構資料表

編寫儲存過程

use Books
GO
if OBJECT_ID('Insert_Books','P') is not null drop procedure dbo.Insert_Books
go
--新增插入儲存過程
CREATE PROCEDURE Insert_Books
@name varchar(100),@price float,@stock int
AS
BEGIN
SET NOCOUNT ON;
insert openquery(POSTGRESQL,'select name,price,stock from books where 1=0')(name,price,stock) values
(@name,@price,@stock);
SET NOCOUNT ON;
END
GO
if OBJECT_ID('update_Books','P') is not null drop procedure dbo.update_Books
go

新增觸發器

--建立新增觸發器
CREATE TRIGGER insert_trigger
ON Books.dbo.books
AFTER INSERT
AS
BEGIN
declare @name varchar(150),@price float,@stock int
select @name=name,@price=price,@stock=stock from inserted
SET NOCOUNT ON; exec LOCALHOSTSQL.[books].[dbo].[Insert_Books] @name,@price,@stock
-- Insert statements for trigger here END

測試效果

同步SQLServer 資料庫中的 資料至PostgreSQL

insert openquery(POSTGRESQL,'select name,price,stock from books where 1=0')
select name,price,stock from books

postgresql資料中

測試新增資料

insert into books(name,price,stock) values('程式碼整潔之道',56.3,623)
select * from books

可以看到當在SQLServer中資料後,PostgreSQL資料庫中的資料也隨之增加了,證明此方法測試執行成功

遇到的問題:

1.無法執行該操作,因為連結伺服器 "XXX" 的 OLE DB 訪問介面 "SQLNCLI10" 無法啟動分散式事務。

在元件服務中->本地DTC->屬性->安全 配置

重啟msdtc 服務 net start msdtc net stop msdtc

2.Microsoft 分散式事務處理協調器(MS DTC)已停止此事務。

檢查連線伺服器配置 ,rpc、rpc out 、rpc 分散式事務連線