MS SQL 事務日誌管理小結

 

本文是對SQL Server事務日誌的總結,文章有一些內容和知識來源於官方文檔或一些技術博客,本文對引用部分的出處都有標註。html

 

 

 

事務日誌介紹sql

 

 

 

SQL Server中,事務日誌是數據庫的重要組件,若是系統出現故障,則可能須要使用事務日誌將數據庫恢復到一致狀態。每一個SQL Server數據庫都擁有本身的事務日誌,用於記錄全部事務以及每一個事務對數據庫所作的修改。那麼數據庫的哪些操做會記錄在事務日誌中呢?具體一點的說,這些操做包括:數據庫

 

 

·         每一個事務的開始和結束。緩存

 

·         每次數據修改(插入、更新或刪除)。 這包括系統存儲過程或數據定義語言 (DDL) 語句對包括系統表在內的任何表所作的更改。安全

 

·         每次分配或釋放區和頁。架構

 

·         建立或刪除表或索引。app

 

 

另外,像SELECT這樣的操做是不會記錄在事務日誌當中的。若是你想對事務日誌記錄信息有一個直觀的認識,那麼你能夠在測試環境作一些SELECTINSERTUPDATEDDL等操做,而後使用ApexSQL Log這款工具查看具體的事務日誌記錄信息。ide

 

 

USE YourSQLDba;工具

GO性能

CREATE TABLE dbo.TEST(ID  INT);

GO

INSERT INTO dbo.TEST SELECT 100;

GO

SELECT * FROM dbo.TEST;

GO

UPDATE dbo.TEST SET ID=101;

GO

DELETE FROM dbo.TEST WHERE ID=101;

GO

 

 

clip_image001

 

如上所示,像DDLDML操做都會記錄在事務日誌當中,可是SELECT是不會記錄在事務日誌當中(固然SELECT INTO除外,其實SELECT INTO在事務日誌裏面轉化爲了CREATE TABLE形式。另外,須要注意: 事務日誌並非審計跟蹤。也就是說事務日誌並不能徹底替代審計跟蹤。它不提供對數據庫作出改變的審計跟蹤;它不保持對數據庫已執行命令的記錄,只有數據如何改變的結果。其實不少對事務日誌瞭解不深刻的人都覺得事務日誌能夠代替審計跟蹤(曾經有項目經理想讓我從事務日誌當中挖掘出誰誤刪了數據,其實事務日誌只會記錄那個帳號刪除了記錄,並不會記錄客戶端信息,因此不能定位到誰刪除了數據)。以下所示,咱們多了一個DROP TABLE操做。你會看到跟上面不同的結果。

 

USE YourSQLDba;

GO

CREATE TABLE dbo.TEST(ID  INT);

GO

INSERT INTO dbo.TEST SELECT 100;

GO

SELECT * FROM dbo.TEST;

GO

UPDATE dbo.TEST SET ID=101;

GO

DELETE FROM dbo.TEST WHERE ID=101;

GO

DROP TABLE dbo.Test;

GO

 

 

clip_image002

 

 

這篇博客transactionlog中有一張圖,描述了一個更新操做的流程中,事務日誌在這個流程中的位置以及做用。想必看過這張圖後,你們在大腦中會對事務日誌的功能做用有一個初步的形象認識。

 

 

clip_image003

 

 

 

其實這張圖還包含了不少隱藏的重要信息,下面咱們一一來述說一下:

 

 

預寫式日誌(Write-Ahead Logging

 

什麼是預寫式日誌呢? 其實其核心思想就是在變化的數據寫入到數據庫以前,將相關日誌記錄信息先寫入到日誌. SQL Server的預寫式日誌(Write-Ahead Logging)機制保證修改的描述(例如日誌記錄)會在數據自己修改寫入數據文件前寫入,會寫入磁盤上的事務日誌文件。它是SQL Server保證事務持久性(Durability)的基本機制。一個日誌記錄會包含已提交事務或未提交事務的詳細信息,在數據被事務修改的不一樣狀況下,可能已經寫入數據文件或還沒來得及寫入數據文件,這取決於檢查點是否已發生。

 

淺談SQL Server中的事務日誌(二)----事務日誌在修改數據時的角色 這篇博客有深刻淺出的介紹(以下所示):

 

Write-Ahead Logging的核心思想是:在數據寫入到數據庫以前,先寫入到日誌.

 

由於對於數據的每筆修改都記錄在日誌中,因此將對於數據的修改實時寫入到磁盤並無太大意義,即便當SQL Server發生意外崩潰時,在恢復(recovery)過程當中那些不應寫入已經寫入到磁盤的數據會被回滾(RollBack),而那些應該寫入磁盤卻沒有寫入的數據會被重作(Redo)。從而保證了持久性(Durability)

 

     WAL不只僅是保證了原子性和持久性。還會提升性能.

     硬盤是經過旋轉來讀取數據,經過WAL技術,每次提交的修改數據的事務並不會立刻反映到數據庫中,而是先記錄到日誌.在隨後的CheckPoint和Lazy Writer中一併提交,若是沒有WAL技術則須要每次提交數據時寫入數據庫......

 

 

官方文檔SQL Server 事務日誌體系結構和管理指南介紹以下(我的對翻譯作了一下調整,也增長了一點點內容):

 

 

要了解預寫日誌的工做方式,瞭解如何將修改的數據寫入磁盤很重要。SQL Server維護一個緩衝區緩存(buffer cache),在必須檢索數據時從其中讀取數據頁。 在緩衝區緩存中修改頁後,不會將其當即寫回磁盤;而是將其標記爲數據。在將數據頁物理寫入磁盤以前,這些髒數據能夠屢次被修改。 對於每次邏輯寫入,都會在日誌緩存(log cache)中插入一條事務日誌記錄記錄這些修改。在將關聯的髒頁從緩衝區緩存中刪除並寫入磁盤以前,必須將這條些日誌記錄寫入磁盤。檢查點進程按期在緩衝區高速緩存中掃描包含來自指定數據庫的頁的緩衝區,而後將全部髒頁寫入磁盤。 CHECKPOINT 可建立一個檢查點,在該點保證所有髒頁都已寫入磁盤,從而在之後的恢復過程當中節省時間。

 

將修改後的數據頁從高速緩衝存儲器寫入磁盤的操做稱爲刷新頁。 SQL Server具備一個邏輯,它能夠在寫入關聯的日誌記錄前防止刷新髒頁。 日誌記錄將在提交事務時寫入磁盤。

 

 

 

檢查點做用

 

 

檢查點將髒數據頁從當前數據庫的緩衝區高速緩存刷新到磁盤上。這最大限度地減小了數據庫完整恢復時必須處理的活動日誌,減小的崩潰恢復須要的時間。其實CheckPoint是爲了優化IO和減小Recovery時間 在完整恢復時,需執行下列操做:

 

§  前滾系統中止以前還沒有刷新到磁盤上的日誌記錄修改信息。

§  回滾與未完成的事務(如沒有 COMMIT ROLLBACK 日誌記錄的事務)相關聯的全部修改。

 

 

 

 

檢查點操做

 

 

 

檢查點在數據庫中執行下列過程:

 

·         將記錄寫入日誌文件,標記檢查點的開始。

 

·         將爲檢查點記錄的信息存儲在檢查點日誌記錄鏈內。

 

·         記錄在檢查點中的一條信息是第一條日誌記錄的日誌序列號 (LSN),它必須存在才能成功進行數據庫範圍內的回滾。  LSN 稱爲最小恢復 LSNMinLSN)。 MinLSN 是下列各項中的最小者:

 

o   檢查點開始的 LSN

o   最先的活動事務起點的 LSN

o   還沒有傳遞給分發數據庫的最先的複製事務起點的 LSN

o   檢查點記錄還包含全部已修改數據庫的活動事務的列表。

 

·         若是數據庫使用簡單恢復模式,檢查點則標記在 MinLSN 前重用的空間。

·         將全部髒日誌和髒數據頁寫入磁盤。

·         將標記檢查點結束的記錄寫入日誌文件。

·         將這條鏈起點的 LSN 寫入數據庫引導頁。

 

 

致使檢查點的活動

 

 

下列情形下將出現檢查點:

 

·         顯式執行 CHECKPOINT 語句。 用於鏈接的當前數據庫中出現檢查點。

·         在數據庫中執行了最小日誌記錄操做,例如,在使用大容量日誌恢復模式的數據庫中執行大容量複製操做。

·         已經使用 ALTER DATABASE 添加或刪除了數據庫文件。

·         經過 SHUTDOWN 語句或經過中止 SQL Server (MSSQLSERVER) 服務中止了 SQL Server 實例。 任一操做都會在 SQL Server 實例的每一個數據庫中生成一個檢查點。

·         SQL Server 實例在每一個數據庫內按期生成自動檢查點,以減小實例恢復數據庫所需的時間。

·         進行了數據庫備份。

·         執行了須要關閉數據庫的活動。 例如,AUTO_CLOSE 設置爲 ON ,而且關閉了數據庫的最後一個用戶鏈接,或者執行了須要從新啓動數據庫的數據庫選項更改。

 

 

事務日誌物理結構

 

 

SQL Server數據庫中的事務日誌能夠有一個或多個事務日誌文件。當存在多個事務日誌文件時,這些日誌文件也只能順序調用,並不能並行使用,所以使用多個日誌文件並不會帶來性能上的提高(後面內容會展開討論這個)。其實,若是你對ORACLE當中聯機重作日誌體系結構很是熟悉的話,多個事務日誌文件就至關於多個redo log file,不一樣的是,ORACLE下面的redo log能夠實現多路複用(日誌組能夠有一個或多個一樣的日誌成員redo log file,多個日誌成員的緣由是防止日誌文件組內某個日誌文件損壞後及時提供備份,因此同一組的日誌成員通常內容信息相同,可是存放位置不一樣)。通常會將同一組的不一樣日誌成員文件放到不一樣的磁盤或不一樣的裸設備上。以提升安全性。SQL Server彷佛沒有這個架構設計。另外,ORACLEREDO UNDO在結構設計上是分開的。而SQL Server能夠經過事務日誌進行REDOUNDO操做。

 

 

clip_image004

 

 

事務日誌邏輯結構

 

 

從邏輯結構上看,SQL Server對於日誌文件的管理,是將邏輯上一個ldf文件劃分紅多個邏輯上的虛擬日誌文件(virtual log files,簡稱VLFs).以便於管理。SQL Server事務日誌按邏輯運行,就好像事務日誌是一串日誌記錄同樣。每條日誌記錄由一個日誌序列號 (LSN) 標識。 每條新日誌記錄均寫入日誌的邏輯結尾處,並使用一個比前面記錄的 LSN 更高的 LSN 日誌記錄按建立時的串行序列存儲。 每條日誌記錄都包含其所屬事務的 ID。對於每一個事務,與事務相關聯的全部日誌記錄經過使用可提升事務回滾速度的向後指針挨個連接在一個鏈中。 虛擬日誌文件沒有固定大小,且物理日誌文件所包含的虛擬日誌文件數不固定。 數據庫引擎在建立或擴展日誌文件時動態選擇虛擬日誌文件的大小。 數據庫引擎嘗試維護少許的虛擬文件。 在擴展日誌文件後,虛擬文件的大小是現有日誌大小和新文件增量大小之和。 管理員不能配置或設置虛擬日誌文件的大小或數量。可是若是設置日誌文件的增量太小,則會產生過多的VLFS,也就是日誌文件碎片,過多的日誌文件碎片會拖累SQL Server性能.所以指定合適的日誌文件初始大小和增加,是減小日誌碎片最關鍵的部分.

 

 

事務日誌是一種迴繞的文件。 例如,假設有一個數據庫,它包含一個分紅四個虛擬日誌文件的物理日誌文件。 當建立數據庫時,邏輯日誌文件從物理日誌文件的始端開始。 新日誌記錄被添加到邏輯日誌的末端,而後向物理日誌的末端擴張。 日誌截斷將釋放記錄所有在最小恢復日誌序列號 (MinLSN) 以前出現的全部虛擬日誌。 MinLSN 是成功進行數據庫範圍內回滾所需的最先日誌記錄的日誌序列號。 示例數據庫中的事務日誌的外觀與下圖所示類似。

 

clip_image006

 

當邏輯日誌的末端到達物理日誌文件的末端時,新的日誌記錄將回繞到物理日誌文件的始端。

 

 

 

clip_image009

 

上面關於事務日誌的虛擬日誌循環覆蓋使用是否有點眼熟的感受,這個跟ORACLEREDO LOG的循環覆蓋使用的理念是如出一轍的。只不過是不一樣的概念和不一樣的實現方式。

 

 

 

事務日誌功能

 

 

 

 

事務日誌有啥功能呢?關於事務日誌的功能,詳細具體內容能夠參考官方文檔事務日誌 (SQL Server),裏面已經詳細介紹了事務日誌的幾個功能,在此不作展開。

 

 

事務日誌支持如下操做:

 

·         恢復個別的事務。

 

·         SQL Server啓動時恢復全部未完成的事務。

 

·         將還原的數據庫、文件、文件組或頁前滾至故障點。

 

·         支持事務複製。

 

·         支持高可用性和災難恢復解決方案: AlwaysOn 可用性組、數據庫鏡像和日誌傳送。

 

 

 

 

事務日誌截斷

 

 

什麼是事務日誌截斷呢? 在介紹事務日誌截斷前,咱們必須先了解一下MinLSN、活動日誌(Actvie Log)等概念。

 

 

最小恢復LSNMinimum Recovery LSNMinLSN)概念

 

 

  MinLSN是在還未結束的事務記錄在日誌中最小的LSN,MinLSN是下列三者之一的最小值:

 

·         CheckPoint的開始LSN

 

·         還未結束的事務在日誌的最小LSN

 

·         還沒有傳遞給分發數據庫的最先的複製事務起點的 LSN.

 

 

 

MinLSN到日誌的邏輯結尾處,則稱爲活動日誌(Active Log)。日誌文件中從 MinLSN 到最後寫入的日誌記錄這一部分稱爲日誌的活動部分,或者稱爲活動日誌(Active log)。 這是進行數據庫完整恢復所需的日誌部分。 永遠不能截斷活動日誌的任何部分。全部的日誌記錄都必須從 MinLSN 以前的日誌部分截斷。也就是說永遠不能截斷活動日誌的任何部分。

 

 

下圖顯示了具備兩個活動事務的結束事務日誌的簡化版本。 檢查點記錄已壓縮成單個記錄。

 

clip_image011 clip_image013 clip_image013[1]

 

LSN 148 是事務日誌中的最後一條記錄。 在處理 LSN 147 處記錄的檢查點時,Tran 1 已經提交,而 Tran 2 是惟一的活動事務。 這就使 Tran 2 的第一條日誌記錄成爲執行最後一個檢查點時處於活動狀態的事務的最舊日誌記錄。 這使 LSN 142Tran 2 的開始事務記錄)成爲 MinLSN

 

 

活動日誌必須包括全部未提交事務的每一部分。若是應用程序開始執行一個事務但未提交或回滾,將會阻止數據庫引擎推動 MinLSN 這可能會致使兩種問題:

 

    若是系統在事務執行了許多未提交的修改後關閉,之後從新啓動時,恢復階段所用的時間將比恢復間隔選項指定的時間長得多。

    由於不能截斷 MinLSN 以後的日誌部分,日誌可能變得很大。 即便數據庫使用的是簡單恢復模式,這種狀況也有可能出現,在簡單恢復模式下,每次執行自動檢查點操做時一般都會截斷事務日誌。

 

日誌截斷其實指從SQL Server數據庫的邏輯事務日誌中刪除不活動的虛擬日誌文件,釋放邏輯日誌中的空間以便物理事務日誌重用這些空間。 若是事務日誌從不截斷,它最終將填滿分配給物理日誌文件的全部磁盤空間。 可是,在截斷日誌前,必須執行檢查點操做。檢查點將當前內存中已修改的頁(稱爲髒頁)和事務日誌信息從內存寫入磁盤。 執行檢查點時,事務日誌的不活動部分將標記爲可重用。 此後,日誌截斷能夠釋放不活動的部分。有關檢查點的詳細信息,請參閱數據庫檢查點 (SQL Server)

 

關於日誌截斷,必須按期截斷事務日誌,防止其佔滿分配給物理日誌文件的磁盤空間。日誌截斷並不減少物理日誌文件的大小。 若要減小物理日誌文件的物理大小,則必須收縮日誌文件。

 

日誌截斷會在下面事件後自動進行截斷:

 

    簡單恢復模式下,在檢查點以後發生。

 

    在完整恢復模式或大容量日誌恢復模式下,若是自上一次備份後生成檢查點,則在日誌備份後進行截斷(除非是僅複製日誌備份)。

 

   CHECKPOINT only truncates the transaction log (marks the VLF for reuse) only in simple recovery model. In Full recovery, you have to take log backup.

 

 

 

實際上,日誌截斷會因爲多種緣由發生延遲。 查詢 sys.databases 目錄視圖的 log_reuse_wait  log_reuse_wait_desc 列,瞭解哪些因素(若是存在)阻止日誌截斷。 下表對這些列的值進行了說明:

 

Log_reuse_wait

Log_reuse_wait_desc

說明

0

NOTHING

當前有一個或多個可重複使用的虛擬日誌文件。

1

CHECKPOINT

自上第二天志截斷以後,還沒有生成檢查點,或者日誌頭還沒有跨一個虛擬日誌文件移動。 (全部恢復模式)

這是日誌截斷延遲的常見緣由。 有關詳細信息,請參閱數據庫檢查點 (SQL Server)

2

LOG_BACKUP

在截斷事務日誌前,須要進行日誌備份。 (僅限完整恢復模式或大容量日誌恢復模式)

完成下一個日誌備份後,一些日誌空間可能變爲可重複使用。

3

ACTIVE_BACKUP_OR_RESTORE

數據備份或還原正在進行(全部恢復模式)。

若是數據備份阻止了日誌截斷,則取消備份操做可能有助於解決備份直接致使的此問題。

4

ACTIVE_TRANSACTION

事務處於活動狀態(全部恢復模式):

一個長時間運行的事務可能存在於日誌備份的開頭。 在這種狀況下,可能須要進行另外一個日誌備份才能釋放空間。 請注意,長時間運行的事務將阻止全部恢復模式下的日誌截斷,包括簡單恢復模式,在該模式下事務日誌通常在每一個自動檢查點截斷。

延遲事務。延遲的事務是有效的活動事務,由於某些資源不可用,其回滾受阻。 有關致使事務延遲的緣由以及如何使它們擺脫延遲狀態的信息,請參閱延遲的事務 (SQL Server)

長時間運行的事務也可能會填滿 tempdb 的事務日誌。 Tempdb 由用戶事務隱式用於內部對象,例如用於排序的工做表、用於哈希的工做文件、遊標工做表,以及行版本控制。 即便用戶事務只包括讀取數據(SELECT 查詢),也可能會以用戶事務的名義建立和使用內部對象, 而後就會填充 tempdb 事務日誌。

5

DATABASE_MIRRORING

數據庫鏡像暫停,或者在高性能模式下,鏡像數據庫明顯滯後於主體數據庫。 (僅限完整恢復模式)

有關詳細信息,請參閱數據庫鏡像 (SQL Server)

6

REPLICATION

在事務複製過程當中,與發佈相關的事務仍未傳遞到分發數據庫。 (僅限完整恢復模式)

有關事務複製的信息,請參閱 SQL Server Replication

7

DATABASE_SNAPSHOT_CREATION

正在建立數據庫快照。 (全部恢復模式)

這是日誌截斷延遲的常見緣由,一般也是主要緣由。

8

LOG_SCAN

發生日誌掃描。 (全部恢復模式)

這是日誌截斷延遲的常見緣由,一般也是主要緣由。

9

AVAILABILITY_REPLICA

可用性組的輔助副本正將此數據庫的事務日誌記錄應用到相應的輔助數據庫。 (完整恢復模式)

有關詳細信息,請參閱:AlwaysOn 可用性組概述 (SQL Server)

10

僅供內部使用

11

僅供內部使用

12

僅供內部使用

13

OLDEST_PAGE

若是將數據庫配置爲使用間接檢查點,數據庫中最先的頁可能比檢查點 LSN 早。 在這種狀況下,最先的頁能夠延遲日誌截斷。 (全部恢復模式)

有關間接檢查點的信息,請參閱數據庫檢查點 (SQL Server)

14

OTHER_TRANSIENT

當前未使用此值。

 

 

 

事務日誌收縮

 

 

 

有時候咱們監控告警會發現事務日誌出現暴增的狀況,那麼此時就必須對是事務日誌進行收縮,無論數據庫處於那種恢復模式,簡單、完整模式。均可以按下面流程進行收縮。

 

 

 

 

1:查看對應數據庫事務日誌的邏輯名稱(name),後續操做須要用到。

 

 

SELECT  database_id ,
        name ,
        type_desc ,
        physical_name
FROM    sys.master_files
WHERE   database_id = DB_ID('YourSQLDba')
    AND type_desc='LOG'

 

 

2: 使用DBCC SQLPERF查看事務日誌空間使用狀況統計信息:

 

 

   

      DBCC SQLPERF (LOGSPACE)

 

   

     若是對應數據庫的Log Space Used(%)的值較小,那麼就能夠收縮事務日誌。

 

 

  3:執行相似下面的收縮事務日誌文件語句。

 

 

USE YourSQLDba;

GO

DBCC SHRINKFILE('YourSQLDba_Log', 128);

 

 

 

  若是Log Space Used(%)很小,而收縮效果又不佳,那麼通常是由於日誌截斷延遲形成,通常能夠經過下面腳本檢查緣由,大部分狀況是由於等待LOG_BACKUP緣故。因此你對事務日誌作一次備份後,再進行收縮便可解決。

 

SELECT  name ,
        log_reuse_wait  ,
        log_reuse_wait_desc
FROM    sys.databases
WHERE   database_id = DB_ID('YourSQLDba');
 
 
backup log [YourSQLDba] 
to disk = 'M:\DB_BACKUP\LOG_BACKUP\YourSQLDba_[2018-01-11_06h37m26_Thu]_logs.TRN' 
with noInit, checksum, name = 'YourSQLDba:15h40: M:\DB_BACKUP\LOG_BACKUP\YourSQLDba_[2018-01-11_06h37m26_Thu]_logs.TRN'
 

 

增長事務日誌文件

 

 

 

SQL Server數據庫中的事務日誌能夠有一個或多個事務日誌文件,可是即便有多個事務日誌文件,也不能並行寫入多個事務日誌文件,數據庫引擎仍是會串行使用多個事務日誌文件。也就是說大多數場景,多個事務日誌文件其實並無什意義,那麼它存在的意義是什麼呢?例如,當你當前磁盤告警,事務日誌沒法繼續增加,你須要在其餘磁盤新增一個事務日誌文件,讓數據庫繼續順暢運行。我的以爲多個事務日誌文件確實是一個很雞肋的東西。Paul S. Randal瞭解SQL Server的日誌記錄和恢復中明確指出:不要建立多個的日誌文件,由於它不會致使性能增益。

 

下面是如何增長一個事務日誌文件的樣例:

 

 

USE [master]
GO
ALTER DATABASE [YourSQLDba] ADD LOG FILE ( NAME = N'YourSQLDba_Log2', FILENAME = N'D:\SQL_LOG\YourSQLDba_Log1.LDF' , SIZE = 65536KB , MAXSIZE = 55296KB , FILEGROWTH = 10%)
GO
 

 

 

 

 

刪除事務日誌文件

 

 

既然能夠增長事務日誌文件,那麼固然也能夠刪除事務日誌文件,可是這個刪除操做是有限制的。主日誌文件(primary log)是不能刪除的。若是你刪除primary log就會報不能從數據庫中刪除主數據文件或主日誌文件。,下面咱們來測試一下。

 

 

準備測試環境以下:

 

 

USE master;
GO
CREATE DATABASE [TEST]
 CONTAINMENT = NONE
 ON  PRIMARY 
( NAME = N'TEST', FILENAME = N'D:\SQL_DATA\TEST.mdf' , SIZE = 100MB , MAXSIZE = 40GB, FILEGROWTH = 64MB )
 LOG ON 
( NAME = N'TEST_log' , FILENAME = N'D:\SQL_LOG\TEST_LOG_1.ldf' , SIZE = 20MB , MAXSIZE = 40MB , FILEGROWTH = 10MB),
( NAME = N'TEST_log2', FILENAME = N'D:\SQL_LOG\TEST_LOG_2.ldf' , SIZE = 20MB , MAXSIZE = 20GB , FILEGROWTH = 10MB)
GO
 
BACKUP DATABASE [TEST] TO  DISK = N'D:\DB_BACKUP\Test.bak' 
        WITH NOFORMAT, NOINIT,  
        NAME = N'TEST-Full Database Backup',
        SKIP, NOREWIND, NOUNLOAD,  STATS = 10;
GO
 
 
USE TEST;
GO
SELECT * INTO mytest FROM sys.objects;
GO
INSERT INTO mytest
SELECT * FROM mytest
GO 12
 
DBCC SQLPERF(LOGSPACE)
 
DBCC LOGINFO('TEST')
 

 

clip_image015

 

 

注意,此時DBCC LOGINFO顯示FileId=3的日誌文件對應的虛擬日誌(VLF)Status2,此時刪除事務日誌文件會提示文件沒法刪除,由於Status=2意味着VLF不能被覆蓋和重用。

 

Status = 2 means that VLF can't be reused (overwritten) at this time and it doesn't necessarily mean that VLF is still active and writing transactions to that VLF. As Jonathan already mentioned, it means that the VLF is waiting for backup/REPL/Mirroring etc..

 

 

USE master;

GO

ALTER DATABASE TEST REMOVE FILE TEST_log2

 

 

 

 

clip_image016

 

 

備份事務日誌後,你會發現FileId=3的日誌文件對應的虛擬日誌(VLF)Status變爲了0,那麼此時就能夠移除事務日誌文件了。

 

 

 

 

BACKUP LOG TEST TO DISK = 'D:\SQL_LOG\Test.Trn'

GO

 

DBCC LOGINFO('TEST')

GO

 

USE master;

GO

ALTER DATABASE TEST REMOVE FILE TEST_log2

 

 

clip_image017

 

 

 

若是是生產環境或者在上述備份事務日誌後,對應日誌文件的VLF的狀態仍然爲2,那麼能夠用收縮日誌文件和備份事務日誌循環處理,直至對應日誌文件下全部的VLF狀態所有爲0,就能夠刪除事務日誌文件。

 

 

USE TEST;

GO 

DBCC SHRINKFILE(TEST_log2);

 

 

BACKUP LOG TEST TO DISK = 'D:\SQL_LOG\Test.Trn'

 

 

 

 

注意,主日誌文件(primary log)是不能刪除的,以下測試所示:

 

 

USE master;

GO

ALTER DATABASE TEST REMOVE FILE TEST_log

 

 

 

Msg 5020, Level 16, State 1, Line 35

The primary data or log file cannot be removed from a database.

 

 

 

 

可是當你須要規劃存儲路徑、移動事務日誌文件時,你可使用折中的方法將主事務日誌文件(primary log)移動到其它目錄。以下所示:

 

 

1: 將當前數據庫脫機;

 

 

ALTER DATABASE TEST SET OFFLINE;

 

 

 

2: 修改數據庫的事務日誌位置

 

 

ALTER DATABASE TEST

MODIFY FILE

(

NAME = N'TEST_log'

, FILENAME = N'E:\SQL_LOG\TEST_LOG_1.ldf'

)

 

 

 

3: 手工將事務日誌文件移動到上面位置

 

 

 

4:將數據庫聯機操做。

 

 

ALTER DATABASE TEST SET ONLINE;

 

 

 

 

另外,如何判斷那個日誌文件是主事務日誌文件?目前來講,我只能這樣判斷, sys.master_files當中,file_id最小值對應的日誌文件爲主事務日誌文件。用腳本判斷以下:

 

 

 

SELECT  f.database_id            AS database_id  ,
        DB_NAME(f.database_id)   AS database_name,
        MIN(f.file_id)           AS primary_log_id ,
        f.type_desc              AS type_desc    
FROM    sys.master_files  f
WHERE  f.database_id= DB_ID('databasename') AND  type = 1
GROUP BY f.database_id,f.type_desc;
 

 

 

另外,你也能夠用下面腳本查出哪些數據庫擁有兩個或以上事務日誌。

 

 

SELECT  f.database_id    AS database_id  ,
        d.name           AS database_name,
        f.type_desc      AS type_desc    ,
        COUNT(*)         AS log_count
FROM    sys.master_files  f
INNER  JOIN sys.databases d ON f.database_id = d.database_id
WHERE   type = 1
GROUP BY f.database_id ,
         f.type_desc,
         d.name
HAVING  COUNT(*) >= 2;
 

 

 

 

 

 

參考資料

 

 

https://docs.microsoft.com/zh-cn/sql/relational-databases/sql-server-transaction-log-architecture-and-management-guide#physical_arch

https://docs.microsoft.com/zh-cn/sql/relational-databases/logs/the-transaction-log-sql-server#FactorsThatDelayTruncation

https://docs.microsoft.com/zh-cn/sql/relational-databases/logs/database-checkpoints-sql-server

https://technet.microsoft.com/zh-cn/library/2009.02.logging.aspx

 

http://www.cnblogs.com/CareySon/archive/2012/02/13/2349751.html

http://www.cnblogs.com/CareySon/p/3315041.html

http://www.cnblogs.com/CareySon/archive/2012/02/17/2355200.html

相關文章
相關標籤/搜索