SQL Server中的事務日誌管理(8/9):優化日誌吞吐量

来源:http://www.cnblogs.com/woodytu/archive/2016/01/11/5046537.html
-Advertisement-
Play Games

當一切正常時,沒有必要特別留意什麼是事務日誌,它是如何工作的。你只要確保每個資料庫都有正確的備份。當出現問題時,事務日誌的理解對於採取修正操作是重要的,尤其在需要緊急恢複數據庫到指定點時。這系列文章會告訴你每個DBA應該知道的具體細節。對於日誌文件的最大日誌吞吐量,我們從存儲架構思路的簡單回顧開始,...


當一切正常時,沒有必要特別留意什麼是事務日誌,它是如何工作的。你只要確保每個資料庫都有正確的備份。當出現問題時,事務日誌的理解對於採取修正操作是重要的,尤其在需要緊急恢複數據庫到指定點時。這系列文章會告訴你每個DBA應該知道的具體細節。


對於日誌文件的最大日誌吞吐量,我們從存儲架構思路的簡單回顧開始,然後進一步看下日誌碎片如何影響需要日誌讀取操作的性能,例如日誌備份,或者故障恢復過程。

最後,我們會談下在日誌大小和增長管理的最佳實踐,還有對過渡日誌增長和碎片的正確處理。

物理架構

正確的物理硬體和架構會幫你保證日誌吞吐量的最大可能,還有一些“黃金法則”。在這之前,已經有人談過了,尤其是Kimberly Tripp在她的《8步走向更好的事務日誌吞吐》里,因此在這裡不會更深入的探討這個話題。

要註意的是,對於日誌文件,在設計內在物理結構時,我們的首要目標是最優日誌寫吞吐量。對於每個添加、刪除或修改數據的事務,SQL Server寫入日誌,這也包括資料庫維護操作,例如索引重建或重組,統計信息更新等等。

你只需要一個日誌文件

從多個日誌文件,在日誌吞吐量方面,不會獲得性能。SQL Server不會並行寫入多個日誌文件。只有一個情況SQL Server會寫入所有日誌文件,那是當在每個日誌文件里更新文件頭時,SQL Server寫入它來更新不同的LSN,例如最後檢查點,最早打開的事務,最後一次日誌備份等等。當只更新文件頭時,很多人會誤認為SQL Server會寫入所有日誌文件。

如果一個資料庫有4個日誌文件,SQL Server會寫入日誌到日誌文件1,直到滿了,然後日誌文件2,日誌文件3和日誌文件4,然後嘗試繞回重新寫入日誌文件1。我們可以通過創建有多個日誌文件(或通過對現存資料庫增加更多文件)的資料庫來驗證下。代碼8.1創建一個Person資料庫,有1個主數據文件和2個日誌文件,每個在不同的硬碟上。

數據和備份文件位置

這篇文章里的例子都假設數據和日誌文件位於D:\SQLData,所有備份位於:D:\SQLBackups,各自不同的位置。當運行這些例子時,直接修改這些位置到你系統合適的位置(並且註意,在實際的系統中,我們不會在同個硬碟上存儲數據和日誌文件)。

註意對於這些數據和日誌文件的大小和文件增長率設置,我們是基於AdventureWorks2008的:

 1 USE master
 2 GO
 3 IF DB_ID('Persons') IS NOT NULL 
 4     DROP DATABASE Persons;
 5 GO
 6 
 7 CREATE DATABASE [Persons] ON PRIMARY 
 8  (   NAME = N'Persons'
 9    , FILENAME = N'D:\SQLData\Persons.mdf'
10    , SIZE = 199680KB
11    , FILEGROWTH = 16384KB
12  )
13  LOG ON
14  (   NAME = N'Persons_log'
15    , FILENAME = N'D:\SQLData\Persons_log.ldf'
16    , SIZE = 2048KB
17    , FILEGROWTH = 16384KB
18  ),
19  (   NAME = N'Persons_log2'
20    , FILENAME = N'C:\SQLData\Persons_log2.ldf'
21    , SIZE = 2048KB
22    , FILEGROWTH = 16384KB
23  )
24 GO
25 
26 ALTER DATABASE Persons SET RECOVERY FULL;
27 
28 USE master
29 GO
30 BACKUP DATABASE Persons
31 TO DISK ='D:\SQLBackups\Persons_full.bak'
32 WITH INIT;
33 GO

代碼8.1:創建有2個日誌文件的Persons資料庫。

接下來,代碼8.2創建一個範例Persons表。

 1 USE Persons
 2 GO
 3 IF EXISTS ( SELECT  *
 4             FROM    sys.objects
 5             WHERE   object_id = OBJECT_ID(N'dbo.Persons')
 6                     AND type = N'U' ) 
 7     DROP TABLE dbo.Persons;
 8 GO
 9 
10 CREATE TABLE dbo.Persons
11     (
12       PersonID INT NOT NULL
13                    IDENTITY ,
14       FName VARCHAR(20) NOT NULL ,
15       LName VARCHAR(30) NOT NULL ,
16       Email VARCHAR(7000) NOT NULL
17     );
18 GO

代碼8.2:創建Persions表。

現在,我們會增加15000行到表,並運行DBCC LOGINFO。註意在我們的測試里,我們從AdventureWorks2005資料庫里的Person.Contact表裡的數據來插入。你也可以使用AdventureWorks2008或AdventureWorks2012資料庫。

 1 INSERT  INTO dbo.Persons
 2         ( FName ,
 3           LName ,
 4           Email
 5         )
 6         SELECT TOP 15000
 7           LEFT(aw1.FirstName, 20) ,
 8                 LEFT(aw1.LastName, 30) ,
 9                 aw1.EmailAddress
10         FROM    AdventureWorks2005.Person.Contact aw1
11         CROSS JOIN AdventureWorks2005.Person.Contact aw2;
12 GO
13 
14 USE Persons
15 GO
16 DBCC LOGINFO;

代碼8.3:插入數據並檢查VLF

SQL Server在主日誌文件里(日誌文件2)連續插入VLF,接下來插入第2個日誌文件(日誌文件3)。而且自動增長了主日誌文件(SQL Server如何自動增長事務日誌的,可以查看這個系列的第2篇文章)。

如果我們繼續增加記錄。SQL Server會繼續增長需要的2個文件,按順序填充VLF,一次一個VLF。圖8.1展示在重新運行代碼8.3,增加95000行後的情形(合計增加了110000行)。現在對於主日誌文件,我們有12個VLF,對於第2個日誌文件我們有8個VLF。

圖8.12個日誌文件的連續使用。

在這個情況里,讀取日誌的任何操作都會始於主日誌里的4個VLF塊開始(FSeqNo 36-39),接下來在第2個日誌文件里的4個塊(FSeqNo 40-43),再接下來是主日誌里的4個塊,以此迴圈。這是為什麼多個日誌文件會降低I/O效率,我們會在下個環節進一步討論。

增加額外日誌文件的唯一原因是一個例外場景,例如,磁碟上的日誌文件滿了(看下第6篇),我們又臨時需要日誌空間,增加額外日誌文件是我們讓SQL Server退出只讀模式的最快方法。但是,一旦額外文件不需要後我們應該將它移除,我們稍後會討論,在 如果出錯了我們該怎麼辦 部分。

對於日誌文件使用專用硬碟/磁碟陣列

把數據文件與日誌文件分別放在不同的硬碟,有很多理由來解釋它為什麼是個很好的做法。首先,在硬碟故障時,這個架構提供更好的恢復機會。例如,如果存儲數據文件的陣列遭受災難性故障,但日誌文件不會和它一起沉船。我們還是有機會進行尾日誌備份,把資料庫恢復到非常接近災難發生的時間點(看下第5篇)。

其次,分離數據文件I/O和日誌文件I/O可以用來優化I/O效率。SQL Server資料庫同時進行隨機和順序I/O操作。順序I/O是SQL Server可以讀寫塊,而不需要請求磁碟上磁頭的重新定位。SQL Server使用順序I/O進行預讀操作,還有所有的事務日誌操作,使用傳統硬碟來說,它是最快的I/O類型。

隨機I/O是讀寫塊時,需要請求磁碟頭改變在磁碟上的位置。這會導致尋求延遲I/O,相對順序I/O,同時降低輸出(MB/s)和性能(IOPS)。一般來說讀操作,尤其在OLTP系統里,是隨機I/O,順序讀取相關的頁小塊是隨機I/O請求的一小部分。

從主順序I/O里分離主要的隨機I/O,我們避免了2者之間的衝突,提高全局的I/O效率。更進一步,對於日誌文件的優化配置並不必和數據文件一樣。通過分離數據和日誌文件,我們可以針對I/O活動類型為每個I/O子系統進行合適配置。例如,選擇優化的RAID配置作為磁碟陣列(下一部分會詳談)。

最後,要提的是在專門磁碟/陣列上的單個日誌文件允許磁頭保持剛好穩定,因為SQL Server是順序寫入日誌的。但是,在單個磁碟/陣列上的多個日誌文件,磁頭會在每個日誌間跳躍;我們沒有順序寫入,沒有磁碟搜索的話,因此我們降低了順序I/O的效率。

理想的情況,每個資料庫都應該在專門的磁碟陣列上有一個日誌文件,但是很多系統這個並不現實,只是個理想。

由於同樣的原因,與順序I/O效率相關,在我們創建日誌文件前,我們要對物理硬碟磁碟碎片整理下,這非常重要。

可能的話,對於日誌硬碟,使用RAID 10

RAID,獨立磁碟冗餘陣列(Redundant Array of Independent Disks)的縮寫,是用來實現下列目標的技術:

  • 提高I/O性能級別,用每秒輸入/輸出操作衡量(Input/Output Operations Per Second(IOPS)),單位大致是(MB/秒/IO以KB為單位的大小)*1024
  • 提高I/O吞吐量,用MB/秒來衡量,單位大致是(IOPS * IO以KB為單位的大小)/1024
  • 提高在單個硬碟里的可用存儲量——你現在還不能購買5TB的單個硬碟,但你可以通過在RAID 5陣列里的6個1TB的硬碟,在操作系統里擁有5TB的硬碟。
  • 獲得數據冗餘,通過在多個硬碟分佈存儲部分信息,或者在陣列里使用物理硬碟鏡像。

RAID級別的選擇很大程度上取決於磁碟必須支持的工作量,如剛纔討論的,對於數據和日誌文件的具體不同I/O工作量,意味著在每個情況下會有不同的RAID配置。

在I/O吞吐量和性能方面,我們應該努力優化日誌文件陣列的順序寫。很多專家認為RAID 1 + 0就這一點而言是最佳選擇,儘管這個是以GB存儲空間最貴花費。

深入RAID

每個RAID級別優劣的完整參考不是這個系列文章的討論範圍。瞭解更多信息,我們請你參考《SQL Server故障排除(Troubleshooting SQL Server)》的第2章。

RAID 1+0是個內嵌的RAID,被稱為“鏡像條帶 ”。它通過每個硬碟的第一鏡像提供冗餘,即RAID 1,然後使用RAID 0條帶化這些鏡像硬碟來提高性能。由於只有磁碟的一半空間可以使用,所以會大大增加成本。然後,這個配置提高冗餘的最佳配置,因為即使多個硬碟損壞,系統還是正常運行的,也不會降低系統性能。

常見的更實惠的備用方法是RAID 5,"部分條帶",在多個硬碟間條帶數據,如RAID 0,只存儲部分數據,提供單個磁碟損壞保護。對於同樣的存儲,與RAID 1 + 0比,RAID 5需要更少的磁碟,且提供優異的讀性能。但是,維護部分化數據引發了寫性能上的損失。對於當下的存儲陣列,這隻是個小問題,這是對於事務日誌文件,很多DBA不推薦它的原因,因為它主要進行的是順序寫,要求最小可能的寫延遲。

假設,如我們剛纔建議的,你能隔離每個資料庫日誌文件在特定的磁碟陣列,至少對於那些有最大I/O工作量的資料庫,對於這些陣列是可以使用更昂貴的RAID 1 + 0,對於更小I/O工作量的資料庫可以使用RAID 5或RAID 1。

瞭解下不同RAID級別提供的I/O性能的情況,邪獵的3個可用配置是針對進行混合隨機讀寫操作性能平衡的400G的資料庫,對於SQL Server,連同理論上的I/O輸出率,基於64K的隨機I/O工作量。

  1. RAID 1使用1個15K RPM的600G硬碟=>11.5MB/秒,185 IOPS
  2. RAID 5使用5個15K RPM的146G硬碟=>22MB/秒,345 IOPS
  3. RAID 1 0使用14個15K RPM的73G硬碟=>101M/秒,1609 IOPS

請註意,這些值都是理論上的,在給出配置里盡基於硬碟的潛在I/O工作量。不考慮其他可能因素,對全局的工作量的影響,包括RAID控制器緩存大小和配置,RAID條帶大小,硬碟分區對齊,NTF格式分配單元大小。確保你選擇硬碟配置的唯一方法要處理好工作量位置,即對你的資料庫的I/O子系統進行合適的基準驗證,尤其是使用率。

對SQL Server進行存儲配置基準驗證

對給出的配置有很多現存的工具進行I/O輸出的衡量,最常用的工具是SQLIOIOmeter。另外,還有SQLIOSim,用來測試磁碟配置的可靠性和完整性。

日誌碎片和讀取日誌操作

第2篇所談的,在內部SQL Server把日誌文件分割為多個子文件,即所謂的虛擬日誌文件(VLF)。對於一個日誌文件,在創建時,SQL Server決定分配給它的VLF的個數的大小,每次日誌增加時,然後增加決定好的VLF個數,基於自動增長率的大小,如下所示(儘管對於很小的增長率,有時候增加的VLF會小於4個):

  • 小於64MB——每次自動增加會創建4個新的VLF
  • 64MB至1GB——8個VLF
  • 大於1GB——16個VLF

例如,如果我們創建一個64MB的日誌文件,設置增長率是16MB,那麼日誌文件初始會有8個VLF,每個8MB大小,每次日誌增長時,SQL Server會增加4個VLF,每個4MB大小。如果資料庫吸引了比預期更多的用戶,但是文件設置還是保持不變,當日誌增長到10GB大小,增長了640倍時,會有超過2500個VLF。

另一方面,如果日誌16GB大小,那麼每次增長會增加16個VLF,每個1GB大小。使用大的VLF,我們會占用日誌的大部分,SQL Server不能截斷,如果一些因素進一步延遲截斷,意味這日誌還要增長,增長得更快。

秘訣是保持正確的平衡。推薦的最大增長大小是8GB(Paul Randal在他的《日誌文件內部和維護》視頻里建議的)。相反的,增長率必須足夠大來避免不合理太多的VLF個數。

有2個主要原因來避免頻繁小的日誌增長。一個如在第7篇里談到的,日誌文件不能獲得即時文件初始化的優勢,因此在資源來說,和數據文件增長比,日誌增長會相對昂貴。另一個是碎片日誌會妨礙讀取日誌操作的性能。

很多操作會需要讀取事務日誌,包括:

  • 完整,差異和日誌備份——儘管只有後來會讀取大量的日誌部分。
  • 故障恢復過程——為了保持數據和日誌的一致性,撤銷任何沒有提交的事務,重做任何已經提交,寫入日誌但沒有寫入數據文件的事務(參考第1篇
  • 事務複製——當從發佈者到訂閱者移動修改時,事務複製日誌閱讀器讀取日誌
  • 資料庫鏡像——在鏡像資料庫上,當從主到鏡像傳送最近的改變時,日誌會被讀取
  • 創建資料庫快照——在運行故障恢復過程時需要讀取日誌
  • DBCC CHECKDB——當它運行時會創建資料庫快照
  • 修改數據抓取——使用事務複製日誌閱讀起來跟蹤數據修改

最後,在一個日誌文件里多少個VLF才合適的問題取決與日誌的大小。通常,微軟認為超過200個VLF可能會有問題,但在一個非常大的日誌文件(例如500GB)只有200個VLF也會是個問題,VLF太大,限制了空間重用。

事務日誌VLF數——太多還是太少?

為了瞭解在日誌讀取時,碎片日誌大小的影響,我們會運行一些測試,來看看在廣泛閱讀日誌的兩個過程的影響,即日誌備份和故障恢復過程。

免責申明

接下來的測試無法反應現實中在伺服器級別硬體上運行的多用戶資料庫,上面有特定的RAID配置等等。我們在安裝在虛擬機上,獨立的SQL Server 2008實例上運行。你的數據會不同,在速度慢的硬碟上測試效果會更明顯。我們只想簡單的演示下日誌碎片問題的影響,還有如何調查這些潛在影響的方法。

最後註意,Linchi Shea已經演示了一個只有16個VLF和2000個VLF之間,數據修改性能上的影響。

日誌備份影響

為了瞭解在日誌備份上,碎片日誌影響的大小,我們會創建PersonsLots資料庫,故意創建一個小的2M日誌文件,強制它在非常小的增長率來創建特別的碎片日誌。我們會插入一些數據,運行大的更新來生成很多日誌記錄,然後運行日誌備份來看看會花多少時間。然後我們在預製好正確大小的日誌文件進行同樣的測試。

首先,我們創建PersonsLots資料庫,日誌文件只有2M大小,自動增長率是2MB。

 1 /*
 2 mdf: initial size 195 MB, 16 MB growth
 3 ldf: initial size 2 MB, 2 MB growth
 4 */
 5 
 6 USE master
 7 GO
 8 IF DB_ID('PersonsLots') IS NOT NULL 
 9     DROP DATABASE PersonsLots;
10 GO
11 
12 -- Clear backup history
13 EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'PersonsLots'
14 GO
15 
16 CREATE DATABASE [PersonsLots] ON PRIMARY 
17  (   NAME = N'PersonsLots'
18    , FILENAME = N'C:\SQLData\PersonsLots.mdf'
19    , SIZE = 199680KB
20    , FILEGROWTH = 16384KB
21  )
22  LOG ON
23  (   NAME = N'PersonsLots_log'
24    , FILENAME = N'D:\SQLData\PersonsLots_log.ldf'
25    , SIZE = 2048KB
26    , FILEGROWTH = 2048KB
27  )
28 GO
29 
30 ALTER DATABASE PersonsLots SET RECOVERY FULL;
31 
32 USE master
33 GO
34 BACKUP DATABASE PersonsLots
35 TO DISK ='D:\SQLBackups\PersonsLots_full.bak'
36 WITH INIT;
37 GO
38 
39 DBCC SQLPERF(LOGSPACE) ;
40 --2 MB, 15% used
41 USE Persons
42 GO
43 DBCC LOGINFO;
44 -- 4 VLFs

代碼8.4:創建PersonsLots資料庫

現在我們在很小的增長率里進行日誌增長,如代碼8.5所示,為了創建特別的碎片日誌文件。

 1 DECLARE @LogGrowth INT = 0;
 2 DECLARE @sSQL NVARCHAR(4000)
 3 WHILE @LogGrowth < 4096
 4 
 5 BEGIN
 6       
 7       SET @sSQL = 'ALTER DATABASE PersonsLots                    MODIFY FILE (NAME = PersonsLots_log,                    SIZE = ' + CAST(4096+2048*@LogGrowth AS VARCHAR(10))                                                              +  'KB );'
 8       EXEC(@sSQL);
 9       SET @LogGrowth = @LogGrowth + 1;
10 END
11 USE PersonsLots
12 GO
13 DBCC LOGINFO
14 --16388 VLFs
15 
16 DBCC SQLPERF (LOGSPACE);
17 -- 8194 MB, 6.3% full

代碼8.5:對資料庫PersonsLots創建非常大的碎片日誌。

這裡我們增長日誌在4096增長率,總大小是8GB(4096+2048*4096KB)。日誌增加了4096倍,每次增加4個VLF,移動有了4+(4096*4)=16388個VLF。

現在重新運行代碼8.2來重建Persons表,但這次在PersonLots資料庫,然後調整代碼8.3來在表裡插入100萬條記錄。現在我們將更新Person表來創建很多日誌記錄。取決於你機器配置,當你運行代碼8.6時,你可以泡上一杯咖啡。

 1 USE PersonsLots
 2 GO
 3 /* this took 6 mins*/
 4 DECLARE @cnt INT;
 5 
 6 SET @cnt = 1;
 7 
 8 WHILE @cnt < 6 
 9     BEGIN;
10         SET @cnt = @cnt + 1;
11         UPDATE  dbo.Persons
12         SET     Email = LEFT(Email + Email, 7000)
13     END;
14 
15 DBCC SQLPERF(LOGSPACE) ;
16 --8194 MB, 67% used
17 DBCC LOGINFO;
18 -- 16388 VLFs

代碼8.6:在Persons表上的一個大更新。

最後,我們可以進行一次日誌備份看看會花多少時間。我們在備份代碼後包含了註釋掉的備份統計信息。

1 USE master
2 GO
3 BACKUP LOG PersonsLots
4 TO DISK ='D:\SQLBackups\PersonsLots_log.trn'
5 WITH INIT;
6 
7 /*Processed 666930 pages for database 'PersonsLots', file 'PersonsLots_log' on file 1.
8 BACKUP LOG successfully processed 666930 pages in 123.263 seconds (42.270 MB/sec).*/

代碼8.7:PersonsLots的日誌備份(碎片日誌)

作為比較,我們重覆同樣的測試,但這次我們會仔細調整資料庫日誌大小,讓它有合理的數目的大小合適的VLF。在代碼8.8,我們重建Persons資料庫,初始日誌大小為2GB(16個VLF,每個128M大小)。然後我們人為增長日誌,只有3步就到8GB大小,包含64個VLF(每個128M的大小)。

 1 USE master
 2 GO
 3 IF DB_ID('Persons') IS NOT NULL 
 4     DROP DATABASE Persons;
 5 GO
 6 
 7 CREATE DATABASE [Persons] ON PRIMARY 
 8  (   NAME = N'Persons'
 9    , FILENAME = N'C:\SQLData\Persons.mdf'
10    , SIZE = 2097152KB
11    , FILEGROWTH = 1048576KB
12  )
13  LOG ON
14  (   NAME = N'Persons_log'
15    , FILENAME = N'D:\SQLData\Persons_log.ldf'
16    , SIZE = 2097152KB
17    , FILEGROWTH = 2097152KB
18  )
19 GO
20 USE Persons
21 GO
22 DBCC LOGINFO;
23 -- 16 VLFs
24 
25 USE master
26 GO
27 ALTER DATABASE Persons MODIFY FILE ( NAME = N'Persons_log', SIZE = 4194304KB )
28 GO
29 -- 32 VLFs
30 
31 ALTER DATABASE Persons MODIFY FILE ( NAME = N'Persons_log', SIZE = 6291456KB )
32 GO
33 -- 48 VLFs
34 
35 ALTER DATABASE Persons MODIFY FILE ( NAME = N'Persons_log', SIZE = 8388608KB )
36 GO
37 -- 64 VLFs
38 
39 ALTER DATABASE Persons SET RECOVERY FULL;
40 
41 USE master
42 GO
43 BACKUP DATABASE Persons
44 TO DISK ='D:\SQLBackups\Persons_full.bak'
45 WITH INIT;
46 GO

代碼8.8:創建Persons資料庫並人為增長日誌。

現在重新運行代碼8.2,8.3(有100萬條記錄)和8.6和我們剛纔測試的一樣。你會發現,沒有發生日誌增長。

代碼8.6運行得很快(在我們的測試里,只要一半的時間)。最後,重新運行日誌備份。

1 USE master
2 GO
3 BACKUP LOG Persons
4 TO DISK ='D:\SQLBackups\Persons_log.trn'
5 WITH INIT;
6 
7 /*Processed 666505 pages for database 'Persons', file 'Persons_log' on file 1. BACKUP LOG successfully processed 666505 pages in 105.706 seconds (49.259 MB/sec).
8 */

代碼8.9:Persons資料庫的日誌備份(無碎片日誌)

在日誌備份的影響相對小,對這個大小的日誌是可覆寫的,與只有64個的,14292個VLF的日誌,備份時間有近15-20%的增長,當然,這個是相對於小資料庫(固然有很嚴重的日誌碎片)。

故障恢復影響

在這些測試里,我們調查在故障恢覆上碎片的影響,因為這個過程需要SQL Server讀取活動日誌,重做或撤銷需要的日誌記錄來返回資料庫到一致的狀態。

大量重做

在第一個例子里,我們重用PersonsLots資料庫,刪除並重建,設置恢復模式為完整,進行完整備份然後插入100萬條記錄,如剛纔所示代碼。

現在,在我們更新這些行前,我們將禁止自動化檢查點。

絕不禁止自動化檢查點!

這裡我們這樣做純粹是測試為目的。在任何正常運行的SQL Server資料庫里我們絕不推薦禁止自動化檢查點

當我們提交隨後的更新時,我們立即關閉資料庫,這樣的話,所有的更新已經寫入日誌但沒有寫入數據文件。因此,在故障恢復期間,SQL Server會需要讀取所有相關的日誌來重做所有的操作。

 1 USE PersonsLots
 2 Go
 3 /*Disable Automatic checkpoints*/
 4 DBCC TRACEON( 3505 )
 5 
 6 /*Turn the flag off once the test is complete!*/
 7 --DBCC TRACEOFF (3505)
 8 
 9 /* this took 5 mins*/
10 BEGIN TRANSACTION
11 DECLARE @cnt INT;
12 
13 SET @cnt = 1;
14 
15 WHILE @cnt < 6 
16     BEGIN;
17         SET @cnt = @cnt + 1;
18         UPDATE  dbo.Persons
19         SET     Email = LEFT(Email + Email, 7000)
20     END;
21 
22 DBCC SQLPERF(LOGSPACE) ;
23 --11170 MB, 100% used
24 USE PersonsLots
25 GO
26 DBCC LOGINFO;
27 -- 22340 VLFs

代碼8.10:PersonsLots——禁止自動化檢查點,在顯性事務里運行更新。

現在我們提交事務,關閉資料庫。

1 /*Commit and immediately Shut down*/    
2 COMMIT TRANSACTION;
3 SHUTDOWN WITH NOWAIT

代碼8.11:提交事務,關閉SQL Server

在重啟SQL Server服務後,在恢復期間,嘗試訪問PersonsLots,你會看到如下信息。

1 USE PersonsLots
2 Go
3 /*Msg 922, Level 14, State 2, Line 1
4 Database 'PersonsLots' is being recovered. Waiting until recovery is finished.*/

代碼8.12:PersonsLots正在進行恢復操作。

在SQL Server開始恢複數據庫前,它需要打開日誌,讀取每個VLF。因為多個VLF的影響會延伸到SQL Server重啟資料庫和開始恢復過程之間的時間。

因此,一旦資料庫是可訪問的,我們可以查看這2個事件之間的錯誤日誌,即總的恢復時間。

 1 EXEC sys.xp_readerrorlog 0, 1, 'PersonsLots'
 2 
 3 /*
 4 2012-10-03 11:28:14.240  Starting up database 'PersonsLots'.
 5 2012-10-03 11:28:26.710  Recovery of database 'PersonsLots' (6) is 0%
 6                          complete (approximately 155 seconds remain).
 7 2012-10-03 11:28:33.000  140 transactions rolled forward in database
 8                          'PersonsLots' (6).
 9 2012-10-03 11:28:33.010  Recovery completed for database PersonsLots
10                          (database ID 6) in 6 second(s)
11                          (analysis 2238 ms, redo 4144 ms, undo 12 ms.)
12 */

代碼8.13:對PersonsLots信息進行錯誤日誌查看。

在SQL Server啟動資料庫和開始恢復進程之間有近12.5秒。這是為什麼會看到資料庫列為“in recovery(在恢復中)”,在錯誤日誌里沒有看到任何初始恢覆信息。恢復進程在7秒內完成。註意,在這三個恢復階段,SQL Server花費更多的時間在重做。

現在讓我們對Persons資料庫(預製日誌文件大小)重做同樣的測試。

 1 USE Persons
 2 Go
 3 /*Disable Automatic checkpoints*/
 4 DBCC TRACEON( 3505 )
 5 --DBCC TRACEOFF (3505)
 6 
 7 USE Persons
 8 Go
 9 BEGIN TRANSACTION
10 DECLARE @cnt INT;
11 
12 SET @cnt = 1;
13 
14 WHILE @cnt < 6 
15     BEGIN;
16         SET @cnt = @cnt + 	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一.前言 我們一起從3個小例子來體驗一下linux內核編程。如下:1.內核編程之hello world2.模塊參數傳遞3.模塊間函數調用二.準備工作 首先,在你的linux系統上面安裝linux頭文件,debian系列:1 $:sudo apt-...
  • centos 7安裝docker什麼是 Docker Docker 是一個開源項目,誕生於 2013 年初,最初是 dotCloud 公司內部的一個業餘項目。它基於 Google 公司推出的 Go 語言實現。 項目後來加入了 Linux 基金會,遵從了 Apache 2.0 協議,項目代碼在 Gi....
  • 註意:我們家的電視是海信的,所以不能代表所有的電視哦~~~ 家裡電視有線電視已經過期很長時間了,早就想把電腦連接到電視上用電視做顯示器的心了,今天來興趣了,就弄了一下!!! 用電腦連接電視需要先解決兩個問題: 1、電視有介面能讓你連,例如HDMI等 備好...
  • 一、全局變數 變數 含義@@ERROR最後一SQL錯誤的錯誤號@@IDENTITY最後一次插入的標識值@@LANGUAGE當前使用的語言名稱@@MAX_CONNETIONS可以創建的、同時連接的最大數目@@ROWCOUNT受上一個SQl語句影響的行數(增加語句)@@SERV...
  • 1創建一個Storage Account1)點擊Browse->Storage accounts2) 填寫Storage account,請記住這個名字,之後創建credential需要用到。3)點擊Create。 一般等待一段時間就好了2 創建container1)All resources->B...
  • YARN DistributedShell源碼分析與修改 轉載請註明出處: "http://www.cnblogs.com/BYRans/" <br/ "1 概述" "2 YARN DistributedShell不能滿足當前需求" "2.1 功能需求" "2.2 YARN Distr...
  • 1.概述 我們熟知的資料庫引擎大部分採用靜態數據類型,即列定義的類型定義了值的存儲,並且值要嚴格滿足列的定義,同一列所有值的存儲方式都相同,比如定義了一個列類型為整型 int,不能在該列上輸入'abc'。SQLite的數據類型則採用了動態類型,列定義不能決定值的存儲,值的存儲由值本身決定,因此在.....
  • 首先大家要知道資料庫是由哪三個部分組成的.解析:01.資料庫文件:*.mdf02.次要數據文件:*.ndf03.日誌文件:*.ldf每個資料庫至少要包含兩個文件:一個數據文件和一個日誌文件.數據文件中包含了資料庫的數據和對象,如表,視圖和索引等;日誌文件中包含了用於恢複數據庫所需的信息.創建資料庫時...
一周排行
    -Advertisement-
    Play Games
  • 前言 插件化的需求主要源於對軟體架構靈活性的追求,特別是在開發大型、複雜或需要不斷更新的軟體系統時,插件化可以提高軟體系統的可擴展性、可定製性、隔離性、安全性、可維護性、模塊化、易於升級和更新以及支持第三方開發等方面的能力,從而滿足不斷變化的業務需求和技術挑戰。 一、插件化探索 在WPF中我們想要開 ...
  • 歡迎ReaLTaiizor是一個用戶友好的、以設計為中心的.NET WinForms項目控制項庫,包含廣泛的組件。您可以使用不同的主題選項對項目進行個性化設置,並自定義用戶控制項,以使您的應用程式更加專業。 項目地址:https://github.com/Taiizor/ReaLTaiizor 步驟1: ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • Channel 是乾什麼的 The System.Threading.Channels namespace provides a set of synchronization data structures for passing data between producers and consume ...
  • efcore如何優雅的實現按年分庫按月分表 介紹 本文ShardinfCore版本 本期主角: ShardingCore 一款ef-core下高性能、輕量級針對分表分庫讀寫分離的解決方案,具有零依賴、零學習成本、零業務代碼入侵適配 距離上次發文.net相關的已經有很久了,期間一直在從事java相關的 ...
  • 前言 Spacesniffer 是一個免費的文件掃描工具,通過使用樹狀圖可視化佈局,可以立即瞭解大文件夾的位置,幫助用戶處理找到這些文件夾 當前系統C盤空間 清理後系統C盤空間 下載 Spacesniffer 下載地址:https://spacesniffer.en.softonic.com/dow ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • 一、ReZero簡介 ReZero是一款.NET中間件 : 全網唯一開源界面操作就能生成API , 可以集成到任何.NET6+ API項目,無破壞性,也可讓非.NET用戶使用exe文件 免費開源:MIT最寬鬆協議 , 一直從事開源事業十年,一直堅持開源 1.1 純ReZero開發 適合.Net Co ...
  • 一:背景 1. 講故事 停了一個月沒有更新文章了,主要是忙於寫 C#內功修煉系列的PPT,現在基本上接近尾聲,可以回頭繼續更新這段時間分析dump的一些事故報告,有朋友微信上找到我,說他們的系統出現了大量的http超時,程式不響應處理了,讓我幫忙看下怎麼回事,dump也抓到了。 二:WinDbg分析 ...
  • 開始做項目管理了(本人3年java,來到這邊之後真沒想到...),天天開會溝通整理需求,他們講話的時候忙裡偷閑整理一下常用的方法,其實語言還是有共通性的,基本上看到方法名就大概能猜出來用法。出去打水的時候看到外面太陽好好,真想在外面坐著曬太陽,回來的時候好兄弟三年前送給我的鍵盤D鍵不靈了,在打"等待 ...