Sql-Server

回滾事務中的腳本化 SQL 部署

  • October 25, 2016

注意:我相信這與其他問題的不同僅僅是因為我想在單個事務下執行的創建腳本的大小。


背景

我正在致力於自動化應用程序數據端的部署。我正在使用團隊現有的腳本。他們似乎放棄一切並重新創造。我沒有太多時間讓它變得完美。

我正在考慮在事務之外執行他們的全部刪除腳本,但至少在事務中執行一個長的“創世”創建腳本,因此如果該部分失敗,它處於一個乾淨的點並且更容易從中恢復。

Genesis.sql 包含 34k 行,似乎都是函式、過程、表、類型等的 CREAT(ions)。

我可以這樣做:

SET XACT_ABORT ON
BEGIN TRAN

# Genesis!

COMMIT TRAN

?

真正讓每個人感到困惑的是腳本中 GO 的影響,有人說它將送出交易,而其他人(在網路上)說 GO 只是客戶端發送批處理的指令。

跟進

到目前為止,這還沒有奏效,寫了新的東西,我看到了這條消息:

COMMIT TRANSACTION 請求沒有對應的 BEGIN TRANSACTION。

但是,我認為這主要是由於一兩個腳本中的語法錯誤(全部連接到 30k 行)並且解析器被拋出。

看來我需要先將腳本虛擬執行到一個空的本地數據庫中,以發現語法錯誤,然後嘗試針對目標環境伺服器。

您的數據庫在發布期間是否線上,或者您是否有維護視窗?

如果您有一個維護視窗並且正在執行企業版,您可以創建一個數據庫快照預部署。

然後,如果您的發布過程沒有正確執行,您可以輕鬆地恢復到快照。

SET XACT_ABORT ON;,就其本身而言,不會做任何事情。您需要BEGIN TRAN;在它之後有一個來啟動將包含所有語句的顯式事務。

我建議將DROP操作作為事務的一部分包含在內,這樣如果出現故障,什麼都不會改變。這裡的主要缺點是,如果您要刪除大型表和/或進行其他大規模數據更改,則可能會產生相當大的事務日誌並花費大量時間。在這種情況下,您在“零停機”情況下(即沒有維護視窗)執行此操作,它可能會鎖定表超過可接受的時間。一個非常大的 Transaction 也可能需要很長時間才能回滾,所以如果你花 1 小時更新數據並發生錯誤,那麼至少需要1 小時才能回滾,然後你再試一次。因此,如果您要修改大量數據,則此選項不是很好。

理想情況下,您將擁有一組代表每個項目的腳本。TRY...CATCH每個腳本都會使用它們自己的、獨立的事務和邏輯來進行 ALTER 等操作。如果在開發期間對系統的更改是針對每個項目進行的,那麼它們應該以相同的方式進行測試,然後再進行生產。當然,我可以在這裡向合唱團講道,因為您說您正在使用現有腳本並且沒有時間使其完美。

關於GO語句混淆:我不確定為什麼這會讓任何人感到困惑,因為它很容易測試。該GO語句不是 SQL Server 見過的,如果出現,您將收到一條很好的錯誤消息。該GO語句是 SQL Server Management Studio (SSMS)、SQLCMD、Visual Studio (VS) 等客戶端程序使用的預設批處理分隔符。這些客戶端程序將解析腳本,分解GO語句上的查詢集(GO在其自己的行,可選地在它後面加上一個整數值,用於重複它上面的批處理的次數),並將每組GO-separated 查詢送出到 SQL Server。這就是為什麼你不能放一個GO進入動態 SQL。它與事務無關。但就推出腳本而言,如果您出於任何原因使用局部變數,則這些變數在語句之外無法生存,GO因為局部變數的範圍僅限於一批語句。但是批次都在同一個 Session 中執行,因此您可以使用基於會話的項目,例如CONTEXT_INFO、臨時表、臨時儲存過程,並從 SQL Server 2016 開始,SESSION_CONTEXT將資訊從一個批次傳遞到隨後的另一個批次。

引用自:https://dba.stackexchange.com/questions/152978