2009-06-25 78 views
7

我有一個使用兩個數據庫的Web應用程序。 DB1用戶執行他們的CRUD(創建,讀取,更新,刪除)操作。數據庫DB2是用於報告目的的不同服務器上的只讀數據庫。每個小時,我的DB1都會保存事務日誌,而在DB2上,我有一份工作可以在DB2上恢復它們​​以保持它最新。在恢復SQL Server數據庫之前等待連接關閉

我面臨的問題是,如果有用戶在DB2上運行報告(經常發生),他們會從sql服務器斷開連接,因爲我獲得了獨佔訪問來還原數據庫。恢復每個日誌所需的時間範圍在1-4分鐘之間。

我該如何實現讓我們稱之爲等待 - 恢復功能,其中我的作業等待用戶的查詢完成,然後再將數據庫切換到獨佔訪問並恢復日誌?

我的機器上運行兩個SQL Server 2008中的64位標準版

回答

2

重要組成部分我的問題是使用池連接 - 在這種情況下,即使沒有報告執行連接保持活着。我修改了我的連接字符串,將連接池設置爲false,並在循環中檢查與報表DB的開放用戶連接,直到值爲0.幸運的是,我不必創建觸發器來將用戶關閉。

1

你可能有一個ALTER DATABASE設置有單個用戶或管理員模式下的「立即ROLLBACK」在裏面。這就是踢出用戶的原因。拿出這個條款,它會等待他們離開(但不會阻止新來的)。

RE:你殺死sProc:你可能想看看「WITH IMMEDIATE ROLLBACK」選項。

至於阻止新連接:我過去所做的是禁用應用程序用戶的登錄(服務器主體),等待長達10分鐘檢查每分鐘,看看是否每個人都在外面。之後,我執行ALTER DATABASE ...以立即ROLLBACK,然後進入任何需要執行的OPS功能。

我一直很幸運,登錄總是一次性使用應用程序用戶登錄(即SQL登錄僅用於此目的)如果您不能這樣做,那麼我現在唯一可以考慮的其他事情將拒絕對DB用戶(數據庫主體)的CONNECT權限。然後再去掉DENY。我從來沒有這樣做過,但它應該像這樣:

DENY CONNECT TO SomeDBUserName; 
+0

我acctually使用存儲的過程,踢大家出: ALTER PROCEDURE [DBO] [USP_GETEXCLUSIVE] @dbname VARCHAR(100)AS DECLARE @KILL_ID INT DECLARE VARCHAR @QUERY(320) DECLARE GETEXCLUSIVE_CURSOR CURSOR FOR SELECT A.SPID FROM SYSPROCESSES A JOIN SYSDATABASES乙ON A.DBID = B.DBID WHERE [email protected] OPEN GETEXCLUSIVE_CURSOR FETCH NEXT FROM GETEXCLUSIVE_CURSOR INTO @KILL_ID WHILE(@@ FETCH_STATUS = 0) BEGIN SET @QUERY ='KIL L「+ CONVERT(VARCHAR,@ KILL_ID) EXEC(@QUERY) NEXT來去GETEXCLUSIVE_CURSOR INTO @KILL_ID END CLOSE GETEXCLUSIVE_CURSOR DEALLOCATE GETEXCLUSIVE_CURSOR – lstanczyk 2009-06-25 19:13:37

+0

最大的問題是如何不要讓數據庫接受的時間,而新的連接我在等。 – lstanczyk 2009-06-25 19:14:31

0

報告可以重定向到不同的數據庫名稱嗎?如果是,則可以創建DB2的數據庫快照,並從這些快照運行報告。在每次日誌恢復後,您都會創建一個新快照,並將其標記爲'當前快照',並且所有新報告都將開始針對此快照運行。在發佈新日誌時,會創建一個新快照,並且新的報告將違背新的快照,而舊的正在運行的報告將保留在上一個快照中。當上次報告與舊快照一起完成並且不再有用戶引用它時,它可以被刪除。這樣就不會中斷任何報告,但需要額外的存儲空間:每個新日誌都會導致舊快照開始執行受影響頁面的「寫時複製」操作。

0

備份是否需要每隔一小時進行一次,或者另一種複製方法是否比您設置的自定義流程更好地滿足您的需求?你可以做日誌傳送,它可以配置爲每隔一小時發送一次,而SQL Server會自然處理它,在日誌恢復時阻止用戶。

我可以看到你的問題,我不認爲SQL Server具有你正在尋找的功能(阻止新的連接,同時允許現有的連接完成),但還有其他的解決方法,可以讓你相同的複製功能,可能會更好地完成業務需求。

1

我認爲你的恢復是作爲一項工作發生的。那麼你需要的是一個登錄觸發器。這裏是你如何創建一個登錄觸發器:

登錄觸發器

登錄觸發器時將觸發建立會話。此時會引發LOGON事件。

登錄觸發器的生命週期非常簡單:用戶連接到Sql Server,觸發器觸發,隱式事務打開,然後由您決定!如果出於任何原因想要拒絕登錄到Sql Server的嘗試,只需發出ROLLBACK語句即可完成。

下面是一個簡單的登錄觸發器:

USE master; 
GO 
CREATE LOGIN security_login WITH PASSWORD = '[email protected]'; 
GO 
GRANT VIEW SERVER STATE TO security_login; 
GO 
CREATE TRIGGER connection_deny_trigger 
ON ALL SERVER WITH EXECUTE AS 'security_login' 
FOR LOGON 
AS 
BEGIN 
<*Your conditional code goes here*> 
    ROLLBACK; 
END; 

你可以定義你的工作要做到這一點:

  • 步驟1:啓用登錄觸發器
  • 第2步:檢查是否有打開的用戶 連接到您的報告數據庫 循環中,直到值爲0

    SELECT COUNT(*) from sysprocesses where spid in(
    SELECT session_id FROM sys.dm_exec_sessions WHERE is_user_process = 1) AND 
    dbid= DB_ID('YourReportingDatabase') 
    
  • 第3步:設置數據庫爲單用戶和 恢復日誌

  • 步驟4:將DB到多用戶和禁用登錄觸發器

拉吉