數據庫的可靠性
在關系數據庫系統中,我們需要數據庫可靠,所謂的可靠就是當遇見如下兩種情況之一時保證數據庫的一致性:
在系統崩潰/故障等情況下,保證數據庫的一致性
數據不能在多個DML語句同時修改數據的情況下,導致不一致或數據損壞
實際上,上述第二種情況就是並發性所需要解決的問題,傳統關系數據庫中,我們用鎖來解決這個問題,而對於內存 數據庫或帶有樂觀並發控制的數據庫系統,通過多版本並發控制(MVCC)來解決這個問題。因為本篇文章的主旨是討論 日志而不是並發,因此對於上述第二種情況不會詳細解釋。
我們上面還多次提到了一致性(Consistence),在開始了解日志如何維持一致性之前,我們首先要明白什麼是一致 性。一致性在數據庫系統中所指的內容比較廣,一致性不僅僅需要數據庫中的數據滿足各種約束,比如說唯一約束,主 鍵約束等,還需要滿足數據庫設計者心中的隱式約束,簡單的業務約束比如說性別這列只允許男或女,這類隱式約束通 常使用觸發器或約束來實現,或是在數據庫所服務的應用程序中進行約束。
下面我們把一致性的范圍縮減到事務一致性,事務一致性的概念學術上的解釋為:
如果事務執行期間沒有出現系統錯誤或其他事務錯誤,並且數據庫在事務開始期間是數據一致的,那麼在該事務結束 時,我們認為數據庫仍然保證了一致性。
因此,引申出來事務必須滿足原子性,也就是事務不允許部分執行。事務的部分執行等同於將數據庫置於不一致的 境地之下。此外多事務並發執行也可能導致數據庫不一致,除非數據庫系統對並發進行控制。
關於上面的顯式約束,由數據庫系統來實現,比如說違反了一致性約束的語句會導致數據庫系統報錯並拒絕執行。但 一些隱式的事務約束,比如說寫語句的開發人員對系統設計者所設計的規則並不了解,導致了違反業務規則的數據修改 ,這種情況在數據庫端很難探查。但是這種問題通常可以規則到權限控制的領域,我們認為授予某個用戶修改特定數據 的權限,就認為這個用戶應該了解數據庫中隱式和顯式的規則。
除去這些業務上的數據不一致之外,我們需要在系統崩潰等情況下保證數據的一致性,而可能導致這類數據不一致的 情況包括但不限於下面這些情況:
存儲系統損壞,比如說磁盤上字節級別的損壞,這類問題通常可以通過磁盤上的奇偶校驗發現,另外還有一些大一些 的問題,比如說整個存儲系統崩潰。這類問題的修復手段取決於前期工作,比如說備份策略,高可用性架構,SAN Replication等技術。
機房整體損壞,這類問題比較極端,只有異地機房容災可以解決。
系統故障,修改數據的進程都需要事務作為上下文,和其他概念一樣,事務也是有狀態的。而事務狀態通常存儲在易 丟失的主存中,因此,當出現系統故障、進程崩潰等系統失敗時,可能導致事務狀態的丟失,此時,我們就無法得知事 務中的哪部分已經執行而哪部分還未執行,重新運行事務並不會解決這類問題,因為有可能導致事務中某部分的重復執 行。因此解決這類問題的方式就是將事務的狀態以及對數據庫修改的詳細步驟與內存中的數據分開存放,並存儲於磁盤 等穩定的介質中,當系統故障等情況下,我們可以通過這些記錄來將系統恢復到一致性的狀態之下,我們對這類存儲, 稱之為日志。
SQLServer中的日志
SQL Server中靠日志來維護一致性(當然,日志的作用非常多,但一致性是日志的基本功能,其他功能可以看作是額 外的功能)。通常我們創建數據庫的時候,會附帶一個擴展名為ldf的日志文件。日志文件其實本質上就是日志記錄的集 合。在SQL Server中,我們可以通過DBCC LOGINFO來看這個日志的信息,如圖1所示。
圖1.DBCC LOGINFO