本文介紹一種利用 SQL Server 連接服務器、ODBC 驅動、觸發器與存儲過程實現 SQL Server 到 MySQL 單向實時同步的方案,適用於異構數據庫集成、報表系統數據同步等場景。
INSERT/UPDATE/DELETE 觸發器。OPENQUERY 向 MySQL 執行對應 DML。MySQL Connector/ODBC 5.3(32/64 位匹配 SQL Server 版本)。MySQL ODBC 5.3 ANSI Driver。Data Source Name: jtServer: 192.168.5.188User: rootPassword: ******Database: suzhouPort: 3306-- 指向 MySQL
EXEC sp_addlinkedserver
@server = 'jt',
@srvproduct = 'mysql',
@provider = 'MSDASQL',
@datasrc = NULL,
@location = NULL,
@provstr = 'DRIVER={MySQL ODBC 5.3 ANSI Driver};SERVER=192.168.5.188;DATABASE=suzhou;UID=root;PORT=3306;',
@catalog = NULL;
-- 映射登入憑證
EXEC sp_addlinkedsrvlogin
@rmtsrvname = 'jt',
@useself = 'false',
@rmtuser = 'root',
@rmtpassword = 'password';
-- 測試連通性
SELECT * FROM OPENQUERY(jt, 'SELECT * FROM sz;');
EXEC master.dbo.sp_serveroption @server = N'jt', @optname = N'rpc out', @optvalue = N'TRUE'; EXEC master.dbo.sp_serveroption @server = N'jt', @optname = N'remote proc transaction promotion', @optvalue = N'false';
EXEC sp_addlinkedserver
@server = N'loopback',
@srvproduct = N'',
@provider = N'SQLNCLI',
@datasrc = @@SERVERNAME;
EXEC master.dbo.sp_serveroption @server = N'loopback', @optname = N'rpc out', @optvalue = N'TRUE';
EXEC master.dbo.sp_serveroption @server = N'loopback', @optname = N'remote proc transaction promotion', @optvalue = N'false';
作用: 觸發器調用 Loopback 上的存儲過程,避免觸發器直接跨服務器操作導致本地事務升級為分佈式事務(MSDTC),提升穩定性與效能。
SQL Server:
CREATE DATABASE suzhou;
GO
USE suzhou;
GO
CREATE TABLE sz (
id INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
orderno CHAR(20) NOT NULL,
ordertime DATETIME NOT NULL DEFAULT GETDATE(),
remark VARCHAR(200)
);
MySQL:
CREATE DATABASE suzhou;
USE suzhou;
CREATE TABLE sz (
id INT(11) NOT NULL,
orderno CHAR(20) NOT NULL,
ordertime DATETIME(6) NOT NULL,
remark VARCHAR(200),
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT 同步過程:
USE suzhou;
GO
CREATE PROCEDURE sp_insert
@id INT,
@orderno CHAR(20),
@ordertime DATETIME,
@remark VARCHAR(200)
AS
BEGIN
SET NOCOUNT ON;
INSERT OPENQUERY(jt, 'SELECT id, orderno, ordertime, remark FROM sz')
(id, orderno, ordertime, remark)
VALUES (@id, @orderno, @ordertime, @remark);
END;
GO
UPDATE 同步過程:
CREATE PROCEDURE sp_update
@orderno CHAR(20),
@remark VARCHAR(200)
AS
BEGIN
SET NOCOUNT ON;
UPDATE OPENQUERY(jt, 'SELECT orderno, remark FROM sz')
SET remark = @remark
WHERE orderno = @orderno;
END;
GO
DELETE 同步過程:
CREATE PROCEDURE sp_delete
@orderno CHAR(20)
AS
BEGIN
SET NOCOUNT ON;
DELETE OPENQUERY(jt, 'SELECT orderno FROM sz')
WHERE orderno = @orderno;
END;
GO
INSERT 觸發器:
USE suzhou;
GO
ALTER TRIGGER tr_insert_sz ON suzhou.dbo.sz
FOR INSERT
AS
BEGIN
DECLARE @id INT, @orderno CHAR(20), @ordertime DATETIME, @remark VARCHAR(200);
SELECT @id = id, @orderno = orderno, @ordertime = ordertime, @remark = remark FROM inserted;
EXEC loopback.suzhou.dbo.sp_insert @id, @orderno, @ordertime, @remark;
END;
GO
UPDATE 觸發器:
CREATE TRIGGER tr_update_sz ON suzhou.dbo.sz
FOR UPDATE
AS
BEGIN
DECLARE @orderno CHAR(20), @remark VARCHAR(200);
SELECT @orderno = orderno, @remark = remark FROM inserted;
EXEC loopback.suzhou.dbo.sp_update @orderno, @remark;
END;
GO
DELETE 觸發器:
CREATE TRIGGER tr_delete_sz ON suzhou.dbo.sz
FOR DELETE
AS
BEGIN
DECLARE @orderno CHAR(20);
SELECT @orderno = orderno FROM deleted;
EXEC loopback.suzhou.dbo.sp_delete @orderno;
END;
GO