在SQL Server 故障轉移(高可用方案)中,除FCI(實例級故障轉移)外,無論是Always On、Replication、Log Shipping 、Databaes Mirroring,還是異步備份還原,都容易忽略一個問題,那就是SQL Server 登陸賬戶的同步,因爲數據庫級別的高可用方案都沒有同步登陸賬戶(除了SQL Server 2012 的Contained Database,這種數據庫能將login user/pwd包含於db級別中)。尤其對於一個大型的線上業務環境,動輒幾十上百個登陸賬戶的實際應用場景。
本文將使用《SQL Server 登陸賬戶權限克隆》中SQL Server 登陸賬戶權限克隆過程sp_DBA_LoginPermissionsClone,實現SQL Server 登陸賬戶權限的異步同步。這裏的同步,只將生產服務器上SQL Server 登陸賬戶的創建腳本及權限的賦予腳本同步到備用服務器,並不實時創建修改(因爲刪除賬戶後再重新創建同名的賬戶需要重啓服務)。
準備工作:
-
在備份機器SQL Server 的master 庫上創建一個物理表dba_loginPermissionSQL,用於留存生產服務器上SQL Server登陸賬戶的創建腳本和權限賦予腳本
-
創建對錶loginPermissionSQL的插入過程dba_loginPermissionSQL_Insert、刪除的存儲過程dba_loginPermissionSQL_Delete
-
在備份機器SQL Server 實例上創建登陸賬戶,並賦予執行存儲過程dba_loginPermissionSQL_Insert、dba_loginPermissionSQL_Delete的權限
-
在生產機器上創建鏈接到備份機器的鏈接服務器(如果生產機器和備份機器的網絡不通,還需要打通網絡策略)
-
確定生產服務器上需要同步的SQL Server賬戶
在備用服務器上執行如下腳本(賬戶密碼自行調整):
--在備用服務器上執行
USE master
GO
CREATE TABLE dba_loginPermissionSQL(loginPermissionCreateSQL VARCHAR(max),createDate DATETIME)
CREATE LOGIN link_loginClone
WITH PASSWORD='passWord'
,CHECK_POLICY=ON
,CHECK_EXPIRATION=OFF
CREATE USER link_loginClone FROM LOGIN link_loginClone
GO
CREATE PROC dba_loginPermissionSQL_Insert
@sql VARCHAR(max)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO dba_loginPermissionSQL(loginPermissionCreateSQL ,createDate)
VALUES(@sql,GETDATE())
END
GO
CREATE PROC dba_loginPermissionSQL_Delete
AS
BEGIN
SET NOCOUNT ON
DELETE dba_loginPermissionSQL
WHERE createDate<CAST(GETDATE() AS DATE)
END
GO
GRANT EXEC ON OBJECT::dbo.dba_loginPermissionSQL_Insert TO link_loginClone
GRANT EXEC ON OBJECT::dbo.dba_loginPermissionSQL_Delete TO link_loginClone
在生產服務器上創建:
注意,這裏需要替換創建鏈接服務器腳本中的備用服務器IP、端口、登陸名、登陸密碼。
sp_DBA_LoginPermissionsClone 的腳本在《SQL Server 登陸賬戶權限克隆》一文中,直接Copy執行就好。
--在生產服務器創建
--1. 創建存儲過程sp_DBA_LoginPermissionsClone
USE master
GO
--創建鏈接服務器
EXEC master.dbo.sp_addlinkedserver @server = N'LINK_BAKServer'
, @srvproduct=N'BAKServer', @provider=N'SQLNCLI', @datasrc=N'192.168.0.2,1433'
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'LINK_BAKServer'
,@useself=N'False',@locallogin=NULL,@rmtuser=N'link_loginClone',@rmtpassword='passWord'
GO
EXEC master.dbo.sp_serveroption @server=N'LINK_BAKServer', @optname=N'rpc', @optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'LINK_BAKServer', @optname=N'rpc out', @optvalue=N'true'
GO
--創建存儲過程
CREATE PROC dbo.dba_loginReplication
AS
BEGIN
SET NOCOUNT ON
DECLARE @loginName sysname
DECLARE @sql VARCHAR(max)
DECLARE cur CURSOR FOR
SELECT name
from sys.sql_logins
WHERE name NOT IN('sa','##MS_PolicyTsqlExecutionLogin##','##MS_PolicyEventProcessingLogin##')
--在查詢條件排除你認爲不需要的賬戶
OPEN cur
FETCH NEXT FROM cur INTO @loginName
WHILE @@FETCH_STATUS>=0
BEGIN
EXEC sp_DBA_LoginPermissionsClone @loginName,NULL,NULL,@sql OUTPUT
EXEC LINK_BAKServer.master.dbo.dba_loginPermissionSQL_Insert @sql
FETCH NEXT FROM cur INTO @loginName
END
CLOSE cur
DEALLOCATE cur
--清除歷史數據
EXEC LINK_BAKServer.master.dbo.dba_loginPermissionSQL_Delete
END
GO
最後在生產服務器上創建一個作業,定期執行存儲過程 dba_loginReplication 。當然這個週期不需要太頻繁,登陸賬戶變化頻繁的,可以一天執行一次,登陸賬戶不怎麼變動的,可以一週執行一次。具體根據實際情況來定。