PG內核分析 Question and Answer

PG內核分析 Question and Answer

PG系統概述

爲什麼說PG是一種先進的對象—關係數據庫系統

因爲PG它不僅支持關係數據庫的各種功能, 而且還具備類, 繼承等對象數據庫的特徵.

面向對象數據庫技術可望成爲繼關係數據庫技術之後的新一代數據管理技術。

它是一種以關係數據庫和SQL爲基礎, 擴展了抽象數據類型,
從而具備面向對象特徵的數據庫.

PG不是完全的對象數據庫, 而是綜合了在關係數據庫的基礎上,
吸收了對象數據庫的優點發展起來的. 對象數據庫的缺點參見下面所述:

參考: 面向對象數據庫和關係數據庫的區別

面向對象數據庫的產生主要是爲了解決“阻抗失配”,它強調高級程序設計語言與數據庫的無縫連接。什麼叫無縫連接,假設你
不用數據庫,用C語言編了一個程序,你可以不需要(或基本不需要)任何改動就將它作用於數據庫,即你可以用C語言透明訪問數據庫,就好象數據庫根本不存在一樣,所以也有人把面向對象數據庫理解爲語言的持久化。怎麼樣,聽起來挺玄的吧,可是我們自己開發的數據庫系統——OSCAR早就做到了這一點。
由於實現了無縫連接,使得面向對象數據庫能夠支持非常複雜的數據模型,從而特別適用於工程設計領域。打個比方,想象CAD中的一個複雜部件,它可能由成千上萬個不同的零件組成,要是用關係模型中的表來表達,得用多少張表啊?而描述這種複雜的部件,正好是高級程序設計語言的強項。

此外,面向對象數據庫還吸收了面向對象程序設計語言的思想,如支持類、方法、繼承等概念。
面向對象數據庫很好地解決了阻抗失配的問題,但它也有缺點。它的缺點正好是關係數據庫的強項,由於模型較爲複雜(而且缺乏數學基礎),使得很多系統管理功能難以實現(如權限管理),也不具備SQL處理集合數據的強大能力。

總之,數據庫系統發展的趨勢是,面向對象數據庫和關係數據庫將不斷融合。而對象關係數據庫由於繼承了上述兩者的優點,已經成爲目前數據庫發展的主流。

PG的特性都有哪些

擁有與企業級數據庫(如: Oracle, DB2)相媲美的特性, 如完善的SQL標準支持(如:
PG支持SQL92等標準, 詳見官方文檔), 多版本併發控制(即MVCC,
比Oracle數據庫的回滾段機制還要先進), 時間點恢復, 表空間機制(注:
不是所有大型數據庫都能夠支持此高級功能), 異步複製, 嵌套事務, 在線/熱備份,
一個複雜的查詢優化器, 預寫日誌容錯技術.

它支持國際字符集, 多字節字符編碼, Unicode, 並且對格式化, 排序,
大小寫敏感提供本地化支持.

PG在管理海量數據方面有良好的可擴展性, 對併發用戶管理具有自適應性.
目前已經出現具有管理超過4萬億字節(約3725GB, 或3.6PB, 注意: 這只是單機PG的能力,
通過citus或 PG RAC等分佈式技術可以更大)數據能力的實用版本產品.

PG的代碼結構是怎麼樣的

PG源代碼包括3400多個文件(截止8.4.1版本).

主要目錄(模塊)及用途如下:

Bootstrap: 用於運行Bootstrap運行模式,該模式主要用來創建初始的模板數據庫.

Main: 主程序模塊,它負責將控制權轉到Postmaster進程或Postgres進程.

Postmaster: 監聽用戶請求的守護進程,並控制Postgres進程的啓動和終止.

Libpq: C/C++的庫函數,處理與客戶端間的通信,幾乎所有的模塊都依賴它.

Tcop: 即Traffic cop(交通警察),
Postgres服務進程的主要處理部分,它調用Parser,Optimizer,Executor和Commands中的函數來執行客戶端提交的查詢.

Parser: 編譯器, 將SQL查詢轉化爲內部查詢樹.

Optimizer: 優化器, 根據查詢樹創建最優的查詢路徑和查詢計劃.

Executor: 執行器, 執行來自Optimizer的查詢計劃.

Commands: 執行非計劃查詢的SQL命令,如創建表命令等.

Catalog: 系統表操作, 包含用於操作系統表的專用函數.

Storage: 管理各種類型的存儲系統(如磁盤,閃存等).

Access: 提供各種存取方法,支持堆,索引等數據的存取.

Nodes: 定義系統內部所用到的節點,鏈表等結構,以及處理這些結構的函數.

Utils: 各種支持函數, 如錯誤報告,各種初始化操作等.

Regex: 正則表達式庫及相關函數,用於支持正則表達式處理.

Rewrite: 查詢重寫, 根據規則系統對查詢進行重寫.

Initdb: 初始化數據庫集簇.

TSearch: 全文檢索.

Psql: 數據庫交互工具.

Port: 平臺兼容性處理相關的函數.

在這裏插入圖片描述

PG的數據庫命令都有哪些

PG的體系結構

PG的體系結構是怎樣的

由5大系統構成:

  1. 連接管理系統(連接管理器)

  2. 編譯執行系統

  3. 存儲管理系統

  4. 事務系統

  5. 系統表

連接管理系統: 接受外部操作對系統的請求, 對操作請求進行預處理和分發,
起系統邏輯控制作用;

編譯執行系統: 由查詢編譯器,查詢執行器組成,
完成操作請求在數據庫中的分析處理和轉化工作, 最終實現物理存儲介質中數據的操作;

存儲管理系統: 由索引管理器,內存管理器, 外存管理器組成, 負責存儲和管理物理數據庫,
提供對編譯查詢系統的支持;

事務系統: 由事務管理器, 日誌管理器, 併發控制, 鎖管理器組成,
日誌管理器和事務管理器完成對操作請求處理的事務一致性支持,
鎖管理器和併發控制提供對併發訪問數據的一致性支持;

系統表: 是PG數據庫的元信息管理中心, 包括數據庫對象信息和數據庫管理控制信息,
系統表管理元數據信息, 將PG數據庫的各個模塊有機連接在一起,
形成一個高效的數據管理系統.

在這裏插入圖片描述

PG中的數據字典角色由誰扮演

在PG數據庫系統中, 系統表扮演着數據庫字典的角色.

在關係數據庫中, 爲了實現數據庫的控制, 必須提供數據庫字典的功能.
數據字典不僅存儲各種對象的描述信息, 而且存儲系統管理所需的各種對象的細節信息.

從內容來看, 數據字典包含數據庫系統中所有對象及其屬性的描述信息,
對象之間關係的描述信息,
對象屬性的自然語言含義以及數據字典變化的歷史(即數據庫的狀態信息).

數據字典是關係數據庫系統管理控制信息的核心, 在PG中,
系統表扮演中數據庫字典的角色.

簡介PG數據字典的扮演者—系統表

在關係數據庫中,爲了實現數據庫系統的控制,必須提供數據字典的功能.數據字典不僅存儲各種對象的描述信息,而且存儲系統管理所需的各種對象的細節信息.從內容來看,數據字典包含數據庫系統中所有對象及其屬性的描述信息,對象之間關係的描述信息,對象屬性的自然語言含義以及數據字典變化的歷史(即數據庫的狀態信息).

數據字典是關係數據庫系統管理控制信息的核心,在PG數據庫系統中,系統表扮演着數據字典的角色.

PG的某一個數據庫中都有自己的一套系統表,其中大多數系統表都是在數據庫創建時從模板數據庫中拷貝過來的,因此這些系統表裏的數據都是與所屬數據庫相關的.只有少數系統表是所有數據庫共享的(比如pg_database),
這些系統表裏的數據時關於所有數據庫的.

PG的進程結構是怎樣的

在這裏插入圖片描述

Postgremaster及其子進程是如何通信的

Postgremaster進程在起始時會建立共享內存和信號庫,
Postgremaster及其子進程的通信就是通過共享內存和信號來實現的.

這種多進程設計使得整個系統的穩定性更好,
即使某個後臺進程奔潰也不影響系統中其他進程的工作,
Postgremaster只需要重置共享內存即可從單個後臺進程的奔潰中恢復.

PG7.1版本爲什麼要引進”內存上下文機制”

PG7.1之前的版本在處理大量以指針傳值的查詢時一直存在着內存泄漏問題,
直到查詢結束後才能將內存收回.

爲了解決這個問題, 從版本7.1開始, 系統實現了新的內存管理機制,
這樣使得運行時大多數內存分配操作在各個語義的內存上下文(MemoryContext)中進行.

內存上下文釋放時將會釋放在其中分配的所有內存,
這樣即使某些內存沒有被任何指針指向或忘記了釋放,
我們也可以通過釋放內存上下文來避免這些內存泄漏.

這一機制也使得內存管理更加方便, 開發人員不必再費盡心思的處理內存釋放的工作.

內存上下文具體是如何使用的

  1. 程序首先調用MemoryContextInit創建TopMemoryContext和ErrorContext.

  2. 然後調用AllocSetContextCreate以TopMemoryContext爲根節點創建PostmasterContext

  3. 最後, 將全局指針CurrentMemoryContext指向PostmasterContext.

這些內存上下文的具體含義如下:

  1. TopMemoryContext: 在其中分配的內存直到系統退出時纔會釋放. 例如:
    其中存放了所有打開的文件描述符, 內存上下文的控制節點等.
    它是所有內存上下文的樹根.

  2. ErrorContext: 這是錯誤恢復處理的永久性內存環境, 恢復完畢則重設.

  3. PostmasterContext: 這是Postmaster正常工作的內存環境,
    由它通過fork函數產生的子進程將會刪除這個環境.

PG 配置參數(GUC)

在初始化內存環境之後, 需要配置Postmaster運行時所需的各種參數. GUC(Grand Unified
Configuration)模塊實現了多種數據類型(目前有boolean, int, float,
string四種)的變量配置.這些參數可能由不同的進程在不同的時機進行配置,系統會根據既定的優先權來確定什麼情況下的配置可以生效.

PG的輔助進程都有哪些

共6個:

  1. SysLogger 系統日誌進程

  2. BgWriteer 後臺寫進程

  3. WalWriter 預寫式日誌寫進程

  4. PgArch 預寫式歸檔進程

  5. AutoVacuum系統自動清理進程

  6. PgStat 統計數據收集進程

各個輔助進程的入庫文件都是哪些

在這裏插入圖片描述

PG各個輔助進程簡要介紹

SysLogger系統日誌進程

日誌信息是數據庫管理員獲取數據庫系統運行狀態的有效手段.在數據庫出現故障時,日誌信息是非常.把數據庫日誌信息集中輸出到一個位置將極大方便管理員維護數據庫系統.然而,日誌輸出將產生大量數據(特別是在比較高的調試級別上),單文件保存時不利於日誌文件的操作.因此,
在SysLogger的配置選項中可以調協日誌文件的大小,
SysLogger會在日誌文件達到指定的大小時關閉當前日誌文件,產生新的日誌文件.

BgWriter後臺寫進程 ***

BgWriter是PG後臺將髒頁寫出到磁盤的輔助進程.

引入該進程主要爲達到如下兩個目的:

  1. 首先,
    數據庫在進行查詢處理時若發現要讀取的數據不在緩衝區中時要先從磁盤中讀入要讀取的數據所在的頁面,此時如果緩衝區已滿,則需要先選擇部分緩衝區中頁面替換出去.如果被替換的頁面沒有被修改過,那麼可以直接丟棄;但如果要被替換的頁已被修改,則必需先將這頁寫出到磁盤中後才能替換,這樣數據庫的查詢處理被阻塞.通過使用BgWrite定期寫出緩衝區中部分髒頁到磁盤中,
    爲緩衝區騰出空間,就可以降低查詢處理被阻塞的可能性.

  2. 其次, PG在定期作檢查點時需要把所有髒頁寫出到磁盤,
    通過BgWriter預先寫出一些髒頁,可以減少調協檢查點(CheckPoint,
    數據庫恢復技術的一種)時要進行的IO操作,使系統的IO負載趨向平穩.通過BgWriter對共享緩衝區寫操作的統一管理,避免了其他服務進程在需要讀入新的頁面到共享緩衝區時,不得不將之前修改過的頁面寫出到磁盤的操作.不過,當BgWriter同時也負責處理所有檢查點,它也會定期地發出一個檢查點請求,當然也可以由其他進程通過信號要求BgWriter執行一個檢查點.

WalWriter預寫式日誌寫進程 *****

預寫式日誌WAL(Write Ahead Log,
也稱爲XLog)的中心思想是對數據庫文件的修改必須是隻能發生在這些修改已經記錄到日誌之後,
也就是先寫日誌後寫數據.

如果遵循這個過程,那麼就不需要在每次事務提交的時候都把數據塊刷回到磁盤,因爲在出現崩潰的情況下可以用日誌來恢復數據庫.

使用WAL主要的好處就是顯著地減少了寫磁盤的次數,因爲在日誌提交的時候只需要把日誌文件刷新到磁盤,而不是事務修改的所有數據文件.

在多用戶環境裏,許多事務的提交可以用日誌文件的fsync來完成.

而且日誌文件是順序寫的, 因此同步日誌的開銷遠比同步數據塊的開銷要小.

WalWrite的PG8.3以後才新加入的新特性,它避免了其他服務進程在事務提交時需要同步的寫入預寫式日誌到磁盤,
以使得事務提交記錄不是在提交時同步寫入磁盤,
而是在一個已知的預先設置的時間異步的寫入.

同BgWriter一樣, 其他服務進程在WalWriter出錯時也允許直接進行預寫式日誌寫操作.

PgArch預寫式日誌歸檔進程

PG從8.x版本開始提出了PITR(Point-In-Time-Recovery)技術,
支持將數據庫恢復到其運行歷史中任意一個有記錄的時間點.

除2.5.3節中所述的WalWriter外,
PITR的另一個重要的基礎就是對WAL文件(即XLog)的歸檔功能.

PgArch輔助進程的目標就是對WAL日誌在磁盤上的存儲形式(Xlog文件)進行歸檔備份.

AutoVacuum系統自動清理進程

在PG數據庫中,對錶元組的UPDATE或DELETE操作並未立即刪除舊版本的數據,表中的舊元組只是被標記爲刪除狀態,並未立即釋放空間.這種處理對於獲取多版本併發控制是必要的,如果一個元組的版本仍有可能被其他事務看到,那麼就不能刪除元組的該版本.

當事務提交後,過期的元組版本對事務不再有效,因而其佔據的空間必須回收以供其他元組使用,以避免對磁盤空間增長的無休止的需求,此時對數據庫的清理工作通過運行VACUMM來實現.

從PG8.1開始,
PG數據庫引入一個額外的可選輔助進程AutoVacuum(系統自動清理進程),自動執行VACUUM和ANALYZE命令,回收被標識爲刪除狀態記錄的空間,更新表的統計信息.

PgStat統計數據收集進程

PgStat輔助進程是PG數據庫系統的統計信息收集器,它專門負責收集數據庫系統運行中的統計信息,
如在一個表和索引上進行了多少次插入與更新操作,
磁盤塊的數量和元組的數量,每個表上最近一次執行清理和分析操作的時間,
以及統計每個用戶自定義函數調用執行的時間等.

PgStat統計數據的主要目的是什麼

PgStat輔助進程收集的統計信息主要用於查詢優化時的代價估算.
在這裏插入圖片描述

2.4 守護進程Postmaster

PG信息及其處理函數列表

信號 信號處理函數
SIGHUP SigHupHandler
SIGINT StatementCancelHandler
SIGTERM die
SIGQUIT quickdie
SIGALRM handle_sig_alarm
SIGPIPE SIG_IGN
SIGUSR1 CatchupInterruptHandler
SIGUSR2 NotifyInterruptHandler
SIGFPE FloatExceptionHandler
SIGCHLD 默認
SIGHUP簡介

典型的例子是一個父進程fork子進程之後,父進程立即退出,這樣子進程所在的進程組將變爲孤兒進程組。這樣的孤兒進程組中的每個停止(Stopped)狀態的每個進程都將收到掛斷信號(SIGHUP),然後又立即收到繼續信號(SIGCONT)。所以fork子進程之後,退出父進程,如果子進程還需要繼續運行,則需要處理掛斷信號,否則進程對掛斷信號的默認處理將是退出。

https://www.cnblogs.com/lvyahui/p/7389554.html

進程退出:SIGINT、SIGTERM和SIGKILL區別

一、SIGINT、SIGTERM和SIGKILL區別

  1. SIGINT與SIGTERM區別
    1)SIGINT關聯ctrl+c
    2)SIGINT只能結束前臺進程
    3)通過ctrl+c對當前進程發送結束信號,信號被進程樹接收到(即:不僅當前進程,子進程也會收到結束信號)

  2. SIGTERM與SIGKILL
    1)SIGTERM可以被阻塞、處理和忽略;因此有的進程不能按預期的結束
    2)kill不使用參數:發送SIGTERM信號,只有當前進程收到信號,若當前進程被kill,則子進程的父進程就會更改爲init,即pid爲1
    3)kill命令的默認不帶參數發生的信號就是SIGTERM,讓程序友好的退出
    ,當程序未退出時,可以使用kill -9強制退出

SIGINT、SIGQUIT、 SIGTERM、SIGSTOP區別
  1. SIGINT

程序終止(interrupt)信號,
在用戶鍵入INTR字符(通常是Ctrl-C)時發出,用於通知前臺進程組終止進程。

  1. SIGQUIT

和SIGINT類似, 但由QUIT字符(通常是Ctrl-\)來控制.
進程在因收到SIGQUIT退出時會產生core文件, 在這個意義上類似於一個程序錯誤信號。

  1. SIGTERM

程序結束(terminate)信號,
與SIGKILL不同的是該信號可以被阻塞和處理。通常用來要求程序自己正常退出,shell命令kill缺省產生這個信號。如果進程終止不了,我們纔會嘗試SIGKILL。

  1. SIGSTOP

停止(stopped)進程的執行. 注意它和terminate以及interrupt的區別:該進程還未結束,
只是暫停執行. 本信號不能被阻塞, 處理或忽略.

SIGALRM

在POSIX兼容的平臺上, SIGALRM是在定時器終止時發送給進程的信息.

SIGPIPE

往一個已經接收到FIN的套接中寫是允許的,接收到的FIN僅僅代表對方不再發送數據。並不能代表我不能發送數據給對方。

往一個FIN結束的進程中寫(write),對方會發送一個RST字段過來,TCP重置。如果再調用write就會產生SIGPIPE信號

通常,我們只需要忽略這個信號即可:signal(SIGPIPE,ISG_IGN);

https://www.cnblogs.com/wsw-seu/p/8413290.html

Linux的SIGUSR1和SIGUSR2信號

SIGUSR1 用戶自定義信號 默認處理:進程終止

SIGUSR2 用戶自定義信號 默認處理:進程終止

當一個進程調用fork時,因爲子進程在開始時複製父進程的存儲映像,信號捕捉函數的地址在子進程中是有意義的,所以子進程繼承父進程的信號處理方式。

但是當子進程調用exec後,因爲exec運行新的程序後會覆蓋從父進程繼承來的存儲映像,那麼信號捕捉函數在新程序中已無意義,所以exec會將原先設置爲要捕捉的信號都更改爲默認動作。

https://www.cnblogs.com/kex1n/p/8296332.html

SIGFPE

在POSIX兼容的平臺上,SIGFPE是當一個進程執行了一個錯誤的算術操作時發送給它的信號。SIGFPE的符號常量在頭文件signal.h中定義。因爲在不同平臺上,信號數字可能變化,因此常使用信號名稱。

SIG是信號名的通用前綴。FPE是floating-point
exception(浮點異常)的首字母縮略字。產生SIGFPE信號時並非一定要涉及浮點算術,之所以不修改名字是因爲這麼做會破壞向下兼容性。
[1]

導致SIGFPE被髮送給進程的原因有很多。一個常見的例子是由於一個意外輸入導致的溢出,或者在程序構造中的錯誤。

SIGFPE可以被處理。也就是說,程序員可以指定他們在接收到信號時想要的動作,例如調用一個子程序,忽略事件等。

SIGCHLD

SIGCHLD,在一個進程終止或者停止時,將SIGCHLD信號發送給其父進程,按系統默認將忽略此信號,如果父進程希望被告知其子系統的這種狀態,則應捕捉此信號。

SIGCHLD屬於unix以及類unix系統的一種信號

產生原因 siginfo_t代碼值

1,子進程已終止 CLD_EXITED

2,子進程異常終止(無core) CLD_KILLED

3,子進程異常終止(有core) CLD_DUMPED

4,被跟蹤子進程以陷入 CLD_TRAPPED

5,子進程已停止 CLD_STOPED

5,停止的子進程已經繼續 CLD_CONTINUED

PG的存儲管理

爲什麼說存儲管理數據庫非常基礎和重要的技術

數據庫管理系統的任務本質上是向存儲設備上寫入或者從存儲設備上讀出數據,
因此對於一個DBMS來說, 存儲的管理是一項非常基礎和重要的技術.

在PG中, 有專門的模塊負責管理存儲設備(包括內存和外存), 我們稱之爲存儲管理器.

存儲管理器提供了一組統一的管理外存和內存資源的功能模塊,
所有對外存和內存的操作都將交由存儲管理器處理,
可以認爲存儲管理器是數據庫管理系統與物理存取設備的接口.

與PG的其他模塊相比, 存儲管理器處在系統結構的底層,
它包含了操作物理存取設備的接口.

3.1 存儲管理的體系結構

存儲管理器的體系結構是怎樣的

在這裏插入圖片描述

爲了防止多個進程併發訪問共享內存中數據時產生衝突, PG是如何處理的

爲了防止多個進程併發訪問共享內存中數據時產生衝突,
PG提供了輕量級鎖,用於支持對共享內存中同一數據的互斥訪問.

使用共享內存有什麼用

PG使用共享內存實現了IPC(進程間通信)以及無效消息共享,用以支持進程間的相互相互通信.

提供內存上下文有什麼用

存儲管理器提供內存上下文(MemoryContext)用於統一管理內存的分配和回收,
從而更加有效安全地對內存空間進行管理.

外存的管理包括哪些

外在的管理包括表文件管理,空閒空間管理,虛擬文件描述符管理以及大數據存儲管理等.

在PG中,
每個表都用一個文件(表文件)存儲,表文件以表的OID命名.對於超出操作系統文件大小限制(比如FAT32限制爲4G)的表文件,
PG會自動將其切分成多個文件來存儲,並在原表文件名的尾部加上切分的順序號來標識它們.

VM和FSM

從PG8.4開始, 每個表除了表文件外還擁有兩個附屬文件:
可見性映射表文件(VM)和空閒空間映射表文件(FSM).

前者用於加快清理操作(VACUMM)的執行速度, 後者則用於表文件空閒空間的管理.

虛擬文件描述符機制

爲了避免超過操作系統對每個進程打開文件數的限制,存儲管理器使用了虛擬文件描述符機制,使得後臺進程可以打開”無限多個”文件.

PG如何支持大數據存儲的

PG提供了大對象機制和TOAST機制, 用以支持大數據存儲.

前者主要用於大尺寸的文件, 後者主要用於變長字符串.

PG支持多種存儲介質(如: 閃存,光盤)的擴展嗎

支持.

PG在存儲管理選擇器中封裝了對具體存儲器的操作接口,
以便擴展支持多種存儲介質(比如對閃存,光盤的支持).

PG中數據在內存中是以何種形式存在的

PG的存儲管理器採用與操作系統類似的分頁存儲管理方式,即數據的在內存中是以頁面塊的形式存在.

每個表文件由什麼組成的

每個表文件由多個BLCKSZ(一個可配置的常量)字節大小的文件塊組成,每個文件塊又可以包含多個元組.

表文件以什麼單位讀入內存中的

表文件是以文件塊爲單位讀入內存中的,每一個文件塊在內存中形成一個頁面塊.

由於頁面塊是文件塊在內存中的存在形式,因此在後文中如不進行特殊說明也會使用頁面來指代文件塊.

表文件的寫入(即落般或刷盤)是以什麼單位寫入的

表文件的寫入也是以頁面塊爲單位.

PG採用的是行存還是列存

PG採用的是傳統的行式存儲, 即以元組爲單位進行數據的存儲.

當然, 數據庫還有”列存”這樣的存儲方式, 使用在特定的場合.

元組可以跨頁面塊(或文件塊)存儲嗎

不能.

PG不支持元組的跨塊存儲,每個元組最大爲MaxHeapTupleSize.

元組不可以跨塊存儲的原因

元組不可以跨塊存儲, 這樣保證了文件塊中存儲的是多個完整的元組.

PG在內存中如何存儲磁盤中的文件塊的

與操作系統一樣,PG在內存中開闢了緩衝區域用於存儲這些文件塊,我們將其在內存中開闢的緩衝區域稱爲緩衝池,
緩衝池被劃分成若干個固定大小(和文件塊的尺寸相同,也是BLCKSZ)的緩衝區,
磁盤上的文件塊讀入內存後被存放在緩衝區中,稱之爲頁面塊或緩衝塊.

BLCKSZ默認大小是多少

BLCKSZ的默認值是8192(即:8K), 因此一個標準(內存)緩衝塊的大小默認爲8KB.

存儲管理器的主要任務包括哪些 **

有6個:

  1. 緩衝池管理

  2. Cache機制

  3. 虛擬文件描述符管理

  4. 空閒空間管理

  5. 進程間通信機制(IPC)

  6. 大數據存儲管理

緩衝池管理幹什麼用的

緩衝池在PG中起緩存的作用.數據庫中的事務常常需要頻繁地存取數據,爲了減少對磁盤的讀寫,在事務執行時,數據首先將會放入緩衝池中,PG設立了進行間共享的緩衝池(共享緩衝池)以及進程私有的催辦(本地緩衝池).

Cache機制有什麼用

將進程最近使用的一些系統數據緩存在其私有內存中,其級別高於緩衝池.

OS已經有文件描述符,爲什麼PG還要虛擬的

PG通過虛擬文件描述符(Vitual File Descriptor, VFD)來對物理文件進行管理,
這樣可以避免因爲操作系統對進程打開文件的限制出現錯誤.

空閒空間管理是什麼東東, 有什麼用

即: FSM, 用於快速定位到表文件中的空閒以便於插入數據,從而提高空間利用率.

PG爲什麼要實現IPC

PG是一個多進程系統,
IPC用來在多個進程後臺進程之間進行通信和消息的傳遞,比如使用消息隊列來同步進程產生的無效消息,同時IPC還提供了對共享內存的管理.

PG在大數據存儲管理方面提供了哪些機制, 各自有什麼區別

PG在大數據存儲管理方面提供了大對象和TOAST機制.
大對象機制是一種由用戶控制的大數據存儲方法,它允許用戶調用函數,通過SQL語句直接向表中插入一個大尺寸文件(如:
圖片,視頻,文檔等).

而TOAST機制則是在用戶插入的變長數據超過一定限度時自動觸發,用戶無法對TOAST加以控制.

前者主要用於大尺寸的文件, 後者主要用於變長字符串.

讀寫元組的過程是怎樣的 ***

在這裏插入圖片描述

3.2 外存管理

外存管理是幹什麼的

外存管理負責處理數據庫與外存介質的交互過程的, 在PG中,
目前只實現了磁盤的管理操作.

其他介質的PG提供了統一的外存操作接口, 需要自己來實現.

3.2.1 表和元組的組織方式
同一個表的元組在表文件中是如何存儲的

在PG中, 同一個表中的元組按照創建的順序依次插入到表文件中的.

備註: 在進行清理操作清除被刪除的元組後,
元組也可以以無序的方式插入到具有空閒空間的文件塊中.

什麼是堆文件

元組之間不進行關聯, 這樣的表文件稱爲堆文件.

PG中有哪些堆文件

4種:

  1. 普通堆

  2. 臨時堆

  3. 序列

  4. TOAST表

元組之間不進行關聯, 這樣的表文件就叫普通堆文件.

臨時堆的結構與普通堆相同,但臨時堆僅在會話過程中臨時創建,會話結束會自動刪除.

序列則是一種元組值自動增長的特殊堆.

TOAST表其實也是一種普通堆,但是它被專門用於存儲變長數據.

儘管這幾種堆文件功能各異,但在底層的文件結構卻是相似的:
每個堆文件都是由多個文件塊組成,在物理磁盤中的存儲形式如圖:

在這裏插入圖片描述

瞭解一下PG中的”HOT技術”

在這裏插入圖片描述

3.2.2 磁盤管理器

磁盤管理器是SMGR的一種具體實現, 它對外提供了管理磁盤介質的接口,
其主要實現在文件md.c中.磁盤管理器並非對磁盤上的文件直接進行操作,
而是通過VFD機制來進行文件操作.

在PG中, 凡是要對存儲在磁盤中的表進行磁盤操作(如打開/關閉,讀/寫等),
都是必須與磁盤管理器打交道, 由它來統一處理.

3.2.3 VFD機制

TODO

3.2.4 空閒空間映射表

隨着表中不斷插入和刪除元組, 文件塊中必然會產生空閒空間(freee space).
在插入元組時優先選擇將其存放在空閒空間內是利用存儲的好方法.
但是這需要在該表衆多擁有空閒空間的文件塊之間進行選擇,
而遍歷所有文件塊進行選擇的開銷將是非常龐大的.在PG8.4之前使用了一種全局FSM文件來記錄所有表文件的空閒空間狀況,
其缺點是在全局FSM文件中只能記錄每個表文件一定數量的文件塊空閒空間狀況.這使得對於空閒空間的管理比較複雜和低效.爲了解決這一問題,
PG8.4中採用了一種新的策略,即對於每個表文件(包括系統表在內),
同時創建一個名爲”關係表OID_fsm”的文件,
用於記錄該表的空閒空間大小,稱之爲空閒空間映射表文件(FSM).

例如, 一個OID爲12000的表, 其空閒空間映射表文件將被命名爲12000_fsm.

3.2.5 可見性映射表

PG中爲了實現多版本併發控制, 錄事務刪除或更新元組時, 並非從物理上刪除,
而是通過將其標記爲無效的方式進行標記刪除,
最終對這些無效元組的清理操作需要調用VACUMM來完成.

3.2.6 大數據存儲

在PG中提供了兩種大數據存儲方式:第一種是TOAST機制, 使用數據壓縮和線外存儲來實現;
第二種是大對象機制, 使用一個專門的系統來存儲大對象數據.

3.3 內存管理

所有數據庫管理系統, 存儲管理中涉及的本質問題是什麼

不管是什麼樣的數據庫管理系統, 其存儲管理中涉及的問題本質是一樣的:
如何減少I/O次數.

在磁盤上讀或寫一個塊大約要花10~30毫秒,在這段時間內一臺普通的機器或許能執行數萬條指令.在通常情況下,讀寫磁盤所用的時間決定了數據庫操作所花費的總時間.

因此, 要儘可能地站最近使用的文件塊停留在內存中,這樣就能有效地減小磁盤I/O的代價.

合理有效的內存管理對於整個DBMS的性能起着非常重要的作用.

PG的內存管理包括哪2個方面

PG中的內存管理包括對共享內存和本地內存的管理.

在這裏插入圖片描述

3.3.1 內存上下文

在PG的舊版本中, 常常需要處理大量以指針傳值的查詢,
因而存在着內存泄漏的問題,直到查詢結束才能將內存收回.
尤其是在處理引用TOAST機制的查詢時, 需要使用大量的內存, 使得這個問題尤爲明顯.

爲此, 從版本7.1開始, PG中實現了新的內存管理機制—內存上下文(MemoryContext).

系統中的內存分配操作在各自語義的內存上下文中進行,所有在內存上下文分配的內存空間都通過內存上下文進行記錄.

因此可以很輕鬆地通過釋放內存上下文來釋放其中的所有內容,而不用費心地釋放其中的每一塊內存,
使得內存分配和釋放更加快捷和可靠,

內存上下文機制借鑑了操作系統的一些概念. 我們知道,
操作竹編爲每個進程分配了進程執行環境, 進程環境之間不互相影響,
由操作系統來對環境進行切換,進程可以在其進程環境中調用一些庫函數(如malloc, free,
realloc等)來執行內存操作.

類似的, 一個內存上下文實際上就相當於一個進程環境,
PG以類似的方式提供了在內存上下文進行內存操作的函數: palloc, pfree, repalloc等.

內存上下文包括了哪幾個重要內容

5部分:

  1. MemoryContext

  2. 內存上下文初始化與創建

  3. 內存上下文中內存的分配

  4. 內存上下文中內存重分配

  5. 釋放內存上下文

3.3.2 高速緩存

當數據庫訪問表時, 需要表的模式信息, 比如表的列屬性,OID,統計信息等.
PG將表的模式信息存放在系統表中,因此要訪問表,就需要首先在系統表中取得表的模式信息.對於一個PG系統來說,
對於系統表的普通表模式的訪問是非常頻繁的. 爲了提高這些訪問的效率,
PG設立了高速緩存(Cache)來提高訪問效率.

爲什麼要設立高速緩存

當數據庫訪問表時,需要表的模式信息,比如表的列屬性,OID,統計信息等.PG將表的模式信息放在系統表中,因此訪問表,就需要首先在系統表中取得表的模式信息.

對於一個PG系統來說,對於系統表和普通表模式的訪問是非常頻繁的.

爲了提高這些訪問的效率,PG設立了高速緩存(Cache)來提高訪問效率.

高速緩存包括幾個部分

高速緩存Cache中包括一個系統表元組Cache(SysCache)和一個表模式信息Cache(RelCache).

SysCache中存放的是最近使用過的系統表的元組,而RelCache中包含所有最近訪問過的表的模式信息(包含系統表的信息).

RelCache中存放的不是元組, 而是RelationData數據結構(數據結構3.13),
每一個RelationData結構表示一個表的模式信息,這些信息都由系統表元組中的信息構造而來.

兩種Cache(SysCache和RelCache)是所有進程共享的嗎

不是.

值得注意的是,
兩種Cache都不是所有進程共享的,每一個PG進程都維護着自己的SysCache和RelCache.

即: 在PG中, 每一個進程都有屬於自己的Cache.

換句話說,
同一個系統表在不同的進程中都有對應的Cache來緩存它的元組(對於RelCache來說緩存的是一個RelationData結構).

說說SysCache

系統表元組Cache(SysCache).

SysCache中存放的是最近使用過的系統表的元組.

說明RelCache

表模式信息Cache(RelCache).

RelCache中包含所有最近訪問過的表的模式信息(包含系統表的信息).

RelCache存放的不是元組, 而是RelationData數據結構(數據結構3.13),
每一個RelationData結構表示一個表的模式信息,
這些信息都由系統表元組中的信息構造而來.

注: 兩種Cache都不是所有進程共享的,
每一個PG的進程都維護着自己的SysCache和RelCache.

兩者的區別
  1. 對RelCache的管理比SysCache要簡單許多,原因在於大多數時候RelCache中存儲的RelationData的結構是不變的,因此PG僅用一個Hash表來維持這樣一個結構.

  2. 對RelCache的查找,插入,刪除,修改等操作也非常簡單

兩者的類似
  1. 和SysCache的初始化類似, RelCache的初始化同樣也在InitPostgres函數中進行,
    同樣分爲兩個階段: RelationCacheInitialize 和 RelationCacheInitializePhase2.
3.3.3 緩衝池管理

如果需要訪問的系統表在Cache中無法找到或者需要訪問普通表的元組,
就需要對緩衝池進行訪問. 任何對於表,元組,索引表等的操作都在緩衝池中進行,
緩衝池的數據調度都以磁盤塊爲單位,
需要訪問的數據以磁盤塊爲單位調用函數smgrread寫入緩衝池,
而smgrwrite將緩衝池數據寫回到磁盤.

調入緩衝池中的磁盤塊稱爲緩衝區, 緩衝塊或者頁面, 多個緩衝區組成了緩衝池.

緩衝池管理模塊的主要結構如下圖.

在這裏插入圖片描述

有了高速緩衝(Cache),爲什麼還要緩衝池

如果需要訪問的系統表元組在Cache中無法找到或者需要訪問普通表的元組,
就需要對緩衝池進行訪問.

任何對於表,元組,索引表等的操作都在緩衝池中進行,緩衝池的數據調度都以磁盤塊爲單位,需要訪問的數據以磁盤塊爲單位調用函數smgrread寫入緩衝池,而smgrread將緩衝池數據寫回到磁盤.調入緩衝池池中的磁盤塊稱爲緩衝區,緩衝塊或者頁面,多個緩衝區組成了緩衝池.

共享緩衝區爲什麼採取了靜態方式 *****

爲了便於實現, PG對共享緩衝區的管理採取了靜態方式:
它在系統配置時規定好了共享緩衝區的總數(1000個, 由全局變量NBuffers定義),
以後在每次系統啓動時,
由Postmaster或某一獨立的Postgres從共享內存中分配一片空間作共享緩衝區,
全部(共享)緩衝區構成共享緩衝池.

緩衝池管理主要有幾塊內容

主要有4塊:

  1. 初始化共享緩衝池

  2. 共享緩衝區查詢

  3. 共享緩衝區替換策略

  4. 本地緩衝池管理

3.3.4 IPC
什麼是IPC

IPC(進程間通信, Inter-Process
Communication)是指至少兩個或者兩個以上的進程交換數據或信號的技術或者方法.

由於進程是操作系統分配資源的最小單位, 每個進程都有自己獨立的一套系統資源,
不同進程之間的資源是相互隔離的.

爲了使不同進程之間能夠互相訪問資源並且進行協同工作, 操作系統提供了IPC機制.

廣義上的IPC不僅可以使用同一計算上的多個進程進行通信,
而且可以使不同計算機上的多個進程進行通信,
但PG中的IPC只考慮同一計算機上的進程間通信.

操作系統爲什麼要提供IPC

爲了使不同進程之間能夠互相訪問資源並且協同工作, 操作系統提供了IPC機制.

PG中的IPC有什麼不同

廣義上的IPC不僅可以使用同一計算上的多個進程進行通信,
而且可以使不同計算機上的多個進程進行通信,
但PG中的IPC只考慮同一計算機上的進程間通信.

IPC的實現方法有哪些

IPC有多種實現方法, 包括文件, Socket, 共享內存等.

PG中的IPC主要採用共享內存的方式來實現,
即在系統中開闢一片所有進程都可以讀寫的內存空間,
並約定好進程讀寫這片內存的時機和方式,
這樣進程之間就可以通過這片共享內存來交換數據.

PG中的IPC額外還提供了哪些功能

在共享內存的基礎上, PG的IPC機制還提供了以下功能:

  1. 進程和Postermaster的通信機制

  2. 統一管理進程的相關變量和函數

  3. 提供了SI Message機制, 即無效消息傳遞機制.

  4. 有關清除的函數.

IPC模塊主要分幾部分內容

共3部分:

  1. 共享內存管理

  2. SI Message

  3. 其他

3.4 表操作與元組操作

3.4.1 表操作

3.4.2 元組操作

3.5 VACUUM機制

爲什麼需要Vacuum機制

當修改元組屬性,執行重建索引等操作時, 特別是當進行多次更新,刪除操作時,
磁盤上會出現很多無效的元組, 佔據了很多磁盤空間並且導致系統性能下降,
這時就需要VACUUM操作清除掉這些”垃圾”.

輔助進程AutoVacuum幹什麼用的

很明顯, 那些經常更新或者刪除元組的表需要比那些較少更新的表清理的更頻繁一些.
PG開啓了一個輔助進程AutoVacuum來執行自動清理工作.

3.5.1 VACUUM操作

3.5.2 Lazy VACUUM

3.5.3 Full VACUUM

3.6 ResourceOwner資源跟蹤

爲什麼要有ResourcesOwner資源跟蹤

在PG中, 每個事務(包括其子事務)在執行時, 需要跟蹤其佔用的內存資源.

例如, 需要跟蹤一個緩衝區的pin鎖或者一個表的鎖資源,
以保證在事務結束或失敗的時候能夠被及時釋放.

PG中使用ResourceOwner對象來對資源集中進行跟蹤.

我們也稱之爲ResourceOwners資源跟蹤器.

ResourceOwner主要記錄哪些資源類型

ResourceOwner記錄了大多數事務過程中使用到的資源, 主要包括:

  1. 父節點,子節點的ResourceOwner指針, 用於構成資源跟蹤器之間的樹狀結構.

  2. 佔用的資源共享緩衝數組和持有的緩衝區pin鎖個數.

  3. Cache的引用次數以及佔用的Cache中存儲的數據鏈表,包括CatCache,
    RelCache以及緩存查詢計劃的PlanCache.

  4. TupleDesc引用次數以及佔用的TupleDesc數組.

  5. Snapshot(見7.10.3節)引用次數以及佔用的Snapshot數組.

索引

什麼是索引

索引是指按表中某些關鍵屬性或表達式建立元組的邏輯順序,
它是由一系列元組的標識號組成的一個列表.

索引的好處

使用索引可以快速訪問表中的特定元組, 被索引的表稱爲基表.

索引改變元組了嗎

索引並不改變表中元組的物理順序, 索引技術會將對於元組的邏輯排序保存在索引文件中.

索引是如何更新的

基表文件中的元組被修改或刪除時, 索引文件會自動更新以保證能夠準確的找到新的數據.

任何一個成熟的數據庫都離不開索引的支持, PG當然也不例外.

PG中的索引類型有哪些

在PG8.4.1中目前支持的索引有: B-Tree索引, Hash索引, GiST索引和GIN索引.

延伸-說一下數據庫有哪些索引類型,有什麼優缺點?

https://blog.csdn.net/qq_39944869/article/details/100532144

4.1 概述

舉例說明索引的好處

假設有下面這樣一個表:

create table student_in_all_countries (

id integer,

name varchar

);

需要大量使用類似下面這樣的語句進行查詢:

select name from student where id=007;

通常, 數據庫系統需要一行一行地掃描整個student表以尋找所有匹配的元組.
如果表student的規模很大(如上student_in_all_countries, 全世界所有國家的學生數量,
恐怕有幾億個), 但是滿足where條件的只有少數幾個(可能是0個或1個),
那麼這種順序掃描的性能就比較差了(注意: 元組在數據庫物理存儲並不是順序的,
而是按照創建順利來的, 所以上面id=007, 有可能需要很大量的順序掃描).

如果讓數據庫系統在id屬性上維護一個索引用於快速定位匹配的元組,那麼數據庫系統只需要在搜索樹中查找少數的幾層就可以找到匹配的元組,
這將大大提高數據查詢的性能.

類似的, 在數據庫中進行更新,刪除操作時也需要先找到要操作的元組,
利用索引同樣可以提升這些操作的性能.

PG提供了哪些索引方式和索引類型

PG8.4.1中一共提供了5種索引方式: 唯一索引, 主鍵索引,
多屬性索引,部分索引,表達式索引以及4中索引類型: B-Tree, Hash, GiST, GIN.

每種索引類型都分別適合某些特定的查詢類型, 因爲他們用了不同的索引結構.

create index命令可以用來創建索引, 默認情況下該命令將創建一個B-Tree索引.

什麼是”從屬索引”

PG裏的所有索引都是”從屬索引”, 也就是說, 索引在物理上與它描述的表文件分離.

索引在數據字典哪裏記錄着

作爲一種數據庫對象, 每個索引都在pg_class表裏面有記錄,
一個索引的內部結構與該索引的訪問方法(索引類型)相關.

一個索引的內部結構與什麼相關

一個索引的內部結構與該索引的訪問訪求(索引類型)相關.

PG所有索引訪問方法是通過什麼來組織的, 如何理解?

PG中所有索引訪問方法都通過頁面來組織索引的內部結構,
這樣可以使用存儲管理器提供的接口來訪問索引.

所有現有的索引訪問方法都使用3.2.1節描述的標準的頁面佈局.

索引的本質是什麼

索引從本質上來說就是一些數據的鍵值與元組標識符(TID, Tuple OID)之間的映射,
這些標識符確定了該索引鍵值在表中對應的元組.

4.1.1 索引方式

PG中共有幾種索引方式, 分別介紹

PG中共有5種索引方式, 即唯一索引,主鍵索引,多屬性索引,部分索引和表達式索引.

唯一索引

如果索引聲明爲唯一索引,
那麼就不允許出現多個索引值相同的元組.唯一索引可以用於強迫索引屬性數值的唯一性,或者是多個屬性組合值的唯一性,唯一索引通過在創建索引命令中加上UNIQUE關鍵字來創建.
一個多字段唯一索引認爲只有兩個元組的所有被索引屬性都相同的時候纔是相同的,
這種重複元組才被拒絕.

目前只有B-Tree可以創建唯一索引.

主鍵索引

如果一個表上定義了一個主鍵,
那麼PG會自動在主鍵屬性上創建唯一索引來實現主鍵約束.可以說,主鍵索引中唯一索引的特殊類型.

多屬性索引

如果一個索引定義在多於一個的屬性上,就稱其爲多屬性索引,它多用於組合查詢.

目前, PG中的B-Tree, GiST和GIN支持多屬性索引, 最多可在32個屬性上創建索引.

雖然PG提供了多屬性索引功能, 但大多數情況下在單個屬性上的索引就足夠了.

除非表的查詢模式非常固定, 否則超過單個屬性的索引幾乎沒有太多用處.

當對一個表創建我屬性索引時,
對於表中的一個元組,會依次讀取出該元組被索引屬性的值,使用這些值一起作爲該元組的索引鍵值.

多屬性索引中不僅可以使用表中的屬性,也可以是使用函數或表達式計算得到的值.

部分索引

建立在一個表上的索引, 該子集由一個條件表達式定義(表達式即部分索引的謂詞),
該索引只包含表中那些滿足這個謂詞的元組.

下面的語句在student表中,
對id在”1”到”255”中的元組name屬性創建索引,這種索引就是部分索引.

create index stu_name_idx on student(name) where (id \> 1 and i \< 255)
表達式索引 *

索引並非一定要建立在一個表的屬性上,還可以建立在一個函數或者從中一個或多個屬性計算出來的標量表達式上.

例如, 可以在student表的name字段上通過小寫函數來創建表達式索引並進行查詢.

創建:

create index stu_low_name_idx on student(lower(name));

查找:

select \* from student where lower(name) = ‘jack’;

4.1.2 索引類型

PG中有幾種索引類型, 分別介紹

PG8.4.1中共有4各索引類型, 下面分別簡單介紹一下.

B-Tree

B-Tree索引使用一種類似於B+樹的結構來存儲數據鍵值,通過這種結構能夠快速地查找索引.B-Tree索引適合支持**比較查詢以及範圍查詢.**在一個建立了B-Tree索引的屬性涉及使用操作符(>,
=, <操作符)進行比較的時候, PG的查詢優化器會考慮使用B-Tree索引進行查找.

Hash

Hash索引使用Hash函數對索引的關鍵字進行散列.

Hash索引只能處理簡單的等於比較.當一個建立了Hash索引的屬性涉及使用”=”操作符進行比較的時候,查詢優化器會考慮使用Hash索引.

GiST

GiST(Generalized Search Tree)意爲通用搜索.嚴格來說,
GiST索引不是一種獨立的索引類型,而是一種架構或者索引模板,可以在這種架構(模板)上實現不同的索引策略.

因此, 可以使用GiST索引的操作符類型高度依賴於索引策略(操作符類).

在以前版本的PG中還有R-Tree索引, 但後來隨着GiST的出現,
取消了R-Tree索引,因爲使用GiST索引的架構可以很容易地實現r-tree索引.

GIN

GIN(Generalized Inverted Index)索引是倒排索引,
它可以處理包含多個鍵的值(比如數組). 與GiST類似, GIN支持用戶定義的索引策略,
對於不同的索引策略, 可以使用的操作符也是不同的.

在後面介紹的Tsearch2全文搜索,
既可以通過GiST來實現,也可以通過GIN實現,兩種各有特點.

4.1.3 索引相關係統表

索引相關的系統表有哪些

爲了管理各種索引類型, PG定義了相關係統表, 這些系統表記錄了索引相關的信息.

每種索引類型都在系統表pg_am(access method)裏面用一個元組來記錄.

pg_am表中的每一個元組包括了該索引類型提供的訪問函數,這些函數是引用自pg_proc系統表中註冊的函數(該系統表存儲了關於函數的信息,
每一個元組表示一個函數),

另外,pg_am中的元組還記錄了索引類型的一些特徵,比如它是否支持多屬性索引等.

在這裏插入圖片描述

4.1.4 索引的操作函數

TODO

4.2 B-Tree索引

4.2.1 B-Tree索引的組織結構

TODO

4.2.2 B-Tree索引的操作

TODO

4.3 Hash索引

4…3.1 Hash索引的組織結構

TODO

4.4 GiST索引

4.4.1 GiST的擴展性

TODO

4.4.2 GiST索引的組織結構

TODO

4.4.3 GiST索引的實現

TODO

4.4.4 GiST索引實例

TODO

4.5 GIN索引

4.5.1 GIN索引的擴展性

TODO

4.5.2 GIN索引的組織結構

TODO

4.5.3 GIN索引的操作

TODO

4.6 TSearch2全文搜索

4.6.1 全文搜索的創建

TODO

4.6.2 全文搜索的查詢

TODO

4.6.3 查詢結果的處理

TODO

4.7 小結

索引是提高數據庫性能的常用方法,
它可以令數據庫服務器以更快的速度查找和檢索特定的行.不過索引也增加了數據庫系統的負荷,因此應該恰當的使用它們.索引的優劣不僅僅與索引的查詢效率有關,同時與索引創建速度,更新速度,索引大小等因素有關.

以上分析的幾種索引使用環境不同,相同環境下使用的優劣也各不相同.

於是,爲了方便用戶對特殊數據類型數據的查詢,PG中提供了索引模板可方便用戶對索引的擴展以支持自定義數據類型上的索引創建和查詢.

通過使用索引,能夠快速查找數據庫中的數據.但在添加索引的同時,會增加數據庫系統的負荷;在增刪修改數據時,
維護索引的一致性也需要一定的時間和空間.由於索引給查找數據帶來的巨大性能提升,因此也得到了廣泛的應用.

在實際的使用中, 應該合理權衡使用索引帶來的利弊, 恰當地使用索引.

PG的查詢編譯

查詢處理器的職責

查詢處理器的職責是數據庫管理系統中的一個部件集合,它允許用戶使用SQL語言在較高層次上表達查詢,
其主要職責是將用戶的各種命令轉化成數據庫上的操作序列並執行.

查詢編譯的主要職責是什麼

查詢編譯的主要任務是根據用戶的查詢語句生成數據庫中最優的執行計劃,在此過程中要考慮視圖,規則以及表的連接路徑等問題.

5.2 查詢分析

查詢分析有幾個模塊

查詢分析是查詢編譯的第一個模塊,它包括3個部分:

  1. 詞法分析

  2. 語法分析

  3. 語義分析

查詢分析的輸出結果是什麼

它將用戶輸入的SQL命令轉換爲查詢樹(Query結構).

查詢分析藉助的分析工具是什麼

其中詞法分析和語法分析分別藉助詞法分析工具Lex和語法分析工具Yacc來完成各自的工作.

分析樹和查詢樹的生成階段

用戶輸入的SQL命令作爲字符串傳遞給查詢分析器,
對其進行詞法分析和語法分析後生成分析樹, 然後進行語義分析得到查詢樹.

查詢分析各個階段對應的處理入口函數有哪些

對於用戶的sQL命令, 統一由exec_simple_query函數處理;

該函數將調用pg_parse_query完成詞法和語法分析併產生分析樹;

接下來調用pg_analyze_and_rewrite函數逐個對分析樹(原始分析樹鏈表raw_parsetree_list
注意: 分析樹可能有多個, 原因:用戶輸入的SQL字符串可能包含多條執行語句,
其對應多個分析樹)進行語義分析和重寫;

在該函數中又會調用函數parse_analyzer進行語義分析並創建查詢樹(Query結構),
函數pg_rewrite_query則負責對查詢樹進行重寫.

查詢分析的處理過程是怎樣的

  1. exec_simple_query調用函數pg_parse_query進入詞法和語法分析的主體處理過程,
    然後函數pg_parse_query調用詞法和語法分析的入口函數raw_parser生成分析樹(原始分析樹鏈表raw_parsetree_list).

  2. 函數pg_parse_query返回分析樹給外部函數 (即: exec_simpe_query)

  3. exec_simple_query接着調用函數pg_analyze_and_rewirte進行語義分析和查詢重寫.首先調用函數parse_analyze進行語義分析並生成查詢樹(用Query結構體表示),
    之後會將技術要求樹傳遞給函數pg_rewrite_query進行查詢重寫.

詞法和語法分析在哪個函數中執行的, 通過哪個工具實現的?

在raw_parser中, 將通過Lex和Yacc生成的代碼來進行詞法和語法分析並生成分析樹.

Lex和Yacc是詞法和語法分析工具,
兩者相配合可以生成助於詞法和語法分析的C語言源代碼.

在raw_parser中,
就是通過調用採用Lex和Yacc預生成的函數base_yyparse來實現詞法和語法分析工作.

Lex工具的職責

Lex用來生成掃描器, 其工作是識別一個一個的模式,
比如數字,字符串,特殊符號等,然後將其傳給Yacc.

Yacc工具的職責

Yacc則用於生成語法分析器, 它識別模式的組合,即語法.

PG中的詞法分析和語法分析是由誰完成的

PG中的詞法分析和語法分析是由Lex和Yacc配合完成的.

詞法和語法分析和各種文件生成和調用關係

在這裏插入圖片描述

詞法和語法分析的入口函數是誰, 返回結果是什麼

詞法和語法分析的入口函數是raw_parser, 該函數返回List結構用於存儲生成的分析樹.

什麼情況下raw_parsettree_list中會含有多個分析樹

在某些情況下,
用戶可能在一個命令字符串中執行多個SQL命令,也就是說客戶端提交給服務進程的字符串包含多個SQL命令.
如: 用戶可能輸入:

“create table t(a int); insert into t values(1);select * from t;”

這樣一個字符串, 那麼PG接收到該字符串之後進行詞法和語法分析的結果就是三個分析樹:
CreateStmt, InsertStmt和SelectStmt.

在返回的raw_parsettree_list中就有三個ListCell分別包含上述三個分析樹.

5.2.3 語義分析

語義分析幹什麼的

語義分析階段會檢查命令中是否有不符合語義規定的成分.

如: 所使用的表,屬性,過程函數等是否存在,聚集函數(如求和函數SUM,
平均函數AVG等)是否可以合法使用等.

其主要作用在於檢查該命令是否可以正確執行.

語義分析相比詞法和語法分析階段的更進之處

語義分析會根據分析樹中的內容得到更有利於執行的數據, 例如: 根據表的名字得到OID,
根據屬性名得到其屬性號, 根據操作符的名字得到其對應的計算函數等.

語義分析在exec_simple_query過程中扮演的角色是什麼樣的

exec_simple_query在從詞法和語法分析模塊獲取了parsetree_list(分析樹鏈表)之後,
會對其中每一棵分析樹調用pg_analyze_and_rewrite進行語義分析和查詢重寫,而在其中負責語義分析的則是analyze.c文件中的parse_analyze函數.

parse_analyze會根據分析樹生成一個對應的查詢樹,而查詢重寫模塊則繼續對這一查詢樹進行修改,
並且有可能會將這個查詢樹改寫成一個包含多棵查詢樹的鏈表.

因此, pg_analyze_and_rewrite最終返回給exec_simple_query的將是一個查詢樹鏈表.

parse_analyze函數中的各個SQL語句命令(xxStmt)處理

在parse_analyze函數中, 將根據命令類型分七種情況處理(參考函數transformStmt).

經過語義分析之後, 會生成查詢樹(Query結構).

其中select/insert/delete/update這四種情況所生成的查詢樹會經由查詢重寫和查詢優化作進一步處理.

兩個重要的結構體Query和ParseState

該過程涉及兩個重要的結構體: Query和ParseState.

Query(用於存儲查詢樹)是查詢分析的最終輸出結果,
其中許多字段可以在分析樹的相關結構體中找到對應項.

ParseState結構體則用於記錄語義分析的中間信息.

parse_analyze處理中遇到的命令類型都有哪些

概要分8種:

  1. 設置分析狀態

  2. Utility (建表,建索引等附件命令)

  3. Explain (顯示查詢的執行計劃)

  4. Declarecursor(定義遊標)

  5. Select

  6. Insert

  7. Delete

  8. Update

各個命令對應的主義分析函數 (列表說明)
NodeTag值 語義分析函數
T_InsertStmt transformInsertStmt
T_DeleteStmt transformDeleteStmt
T_UpdateStmt transformUpdateStmt
T_SelectStmt transformSelectStmt或transformValuesClause
T_DeclareCursorStmt transformDeclareCursorStmt (遊標定義語句)
T_ExplainStmt transformExplainStmt (Explain語句)
其他 作爲Utility類型處理, 直接在分析樹上封裝一個Query節點返回
簡述transformSelectStmt函數的主要處理流程

transfromSelectStmt函數的作用是根據一個SelectStmt結構生成一個查詢樹(Query).

其主要流程如下:

  1. 創建一個新的Query節點, 設置其commandType字段爲CMD_SELECT;

  2. 調用transformWithClause函數處理with子句;

  3. 調用transformFromClause函數處理from子句;

  4. 調用transfomrTargetList函數處理目標屬性;

  5. 調用transformWhereClause函數處理where子句和having子句;

  6. 調用transformSortClause函數處理order by子句;

  7. 調用transformGroupClause函數處理group by子句;

  8. 調用transformDistinctClause函數或transformDistinctOnClause函數處理distinct.

  9. 調用transformLimitClause函數處理limit和offset.

  10. 處理INTO子句;

  11. 設置Query節點的其他標誌(如hasAggs,hasSubLinks等字段);

  12. 返回Query節點.

由此可見,
對於SelectStmt的處理過程被分解成對其各個子句部分的處理,各子句的處理過程相對獨立.

其他類型的分析樹的語法分析過程與此大同小異.

5.3.1 規則系統

查詢重寫的核心是什麼

查詢重寫的核心是規則系統.

規則系統是什麼

規則系統是由一系列的規則組成的, 系統表pg_rewrite存儲重寫規則.

PG的查詢執行

查詢執行器的函數入口和查詢編譯一樣嗎

查詢執行器也是被函數exec_simple_query調用, 只是調用的順序上查詢編譯在前,
查詢執行器在後.

查詢執行器的執行過程

從總體上看, 查詢執行器實際就是按照執行計劃的安排,
有機的調用存儲,索引,併發等模塊,按照各種執行計劃中各種計劃節點的實現算法來完成數據的讀取或者修改的過程.

查詢執行器有幾個子模塊

查詢執行器有4表主要的子模塊:

  1. Portal

  2. ProcessUtility

  3. Executor

  4. 特定功能子模塊

PG事務處理和併發控制

7.1 事務系統簡介

什麼是事務, 事務最大的特點是什麼

事務是數據庫操作的執行單位.

事務最大的特點是: 一個事務提交之後或者完整執行,或者完全不執行, 即沒有中間態.

數據庫中有語句不在事務環境中嗎

沒有, 絕對沒有.

數據庫中, 任何語句的執行都存在於事務環境中, 任何語句開始執行之前事務就開始了.
當語句執行完成後, 事務結束.

什麼是事務環境

通常情況下, 我們提交的查詢語句或者更新語句會被送入一個默認事務環境中執行.
PG中負責管理事務運行的模塊稱爲事務管理器.

事務系統的管理器

3個:

  1. 事務管理器

  2. 鎖管理器

  3. 日誌管理器

事務管理器是事務系統的中樞.

鎖管理器實現了系統併發控制所需要的各種鎖.

日誌管理器用來記錄事務執行的狀態和數據的變化過程.

MVCC應用在事務執行的哪個階段

在PG中, 事務執行的讀階段採用了多版本併發控制(MVCC),
即對元組的讀和寫互不阻塞;而在事務執行的寫階段需要由各種鎖來保證事務的隔離級別.

上下層事務塊的關係

在PG中, 上層的事務塊以及底層的事務塊共同構成了傳統數據庫中所提到的事務的概念.
任何語句的執行總是先進入事務處理接口事務塊中,
然後調用事務底層函數處理具體的命令, 最後返回事務塊中.

事務的執行層次是怎樣的

在這裏插入圖片描述

7.2 事務系統的上層

事務塊和事務的關係

在PG中, 一個事務塊中包含多個事務,
所以事務塊的狀態數量要比底層事務的狀態數量多的多.

PG執行一條SQL對應的事務函數主要有哪些

在PG的事務處理層次中, 位於事務系統上層的是事務塊.

PG執行一條SQL語句前會調用StartTransactionCommand函數,
執行結束時會調用CommitTransactionCommand函數.

如果命令執行失敗, 則會調用AbortCurrentTransaction函數.

上述三個函數根據事務塊的狀態執行不同的操作, 並調用不同的底層事務執行函數.

需要注意的是, 上述三個函數只是進入事務系統上層的入口函數, 並不處理具體事務.

PG爲什麼要將事務系統爲成2個層次

PG將事務系統分成上層(事務塊)和底層(事務)兩個層次, 通過分層的設計,
在處理上層業務的時候可以屏蔽具體細節.

7.2.1 事務塊狀態

7.3 事務系統的底層

7.3.1 事務狀態
7.3.2 事務操作函數
事務操作主要步驟

共4個:

  1. 啓動事務

  2. 提交事務

  3. 退出事務

  4. 清理事務

7.3.3 簡單查詢事務執行過程實例
簡單查詢事務執行過程說明

在這裏插入圖片描述

7.4 事務保存點和子事務

事務保存點和子事務提供了什麼樣的機制

事務保存點(SAVEPOINT)提供了一種機制, 用於回滾部分事務.

PG在實現上把SAVEPOINT認爲是定義子事務的標記. 保存點的作用就是實現事務的回滾,
即從當前子事務回滾到事務鏈(即: 事務塊)中的某個祖先事務.

在PG中, 子事務的主要作用是實現保存點, 從而增強事務操作的靈活性.

7.4.1 保存點實現原理
7.4.2 子事務

7.5 兩階段提交

PG數據庫使用什麼機制來支持分佈式數據庫的事務處理的

PG使用兩階段提交(Two Phase Commit, 2PC)來支持分佈式數據庫的事務處理.

什麼是2pc (兩階段提交), 有什麼作用

2pc分爲a. 預提交階段 和 b. 全局提交階段.

作用: PG使用2pc來支持分佈式數據庫的事務處理.
而實現分佈式事務處理的關鍵就是兩階段提交協議.

分佈式數據(如: RAC)中2pc有什麼用

兩階段提交協議是分佈式數據庫系統中保證分佈式事務ACID特性的經典解決方案.

PG爲其提供了很好的操作接口, 應用程序開發者利用該操作接口可以很好的實現該協議.

7.6 PG的併發控制

PG的併發控制是怎樣的

目標: PG中存在多個會話試圖同時訪問同一數據庫的情況,
併發控制的目標就是保證所有會話高效地訪問, 同時維護數據庫的完整性.

MVCC可以解決所有的併發控制情況嗎

不能.

在PG中也有表和行級別的鎖定機制, 因爲MVCC並不能解決所有的併發控制情況,
所以還需要使用傳統的數據庫中的鎖機制保證事務的併發.

另外, PG還提供了會話鎖機制, 利用它可以擴大鎖的使用範圍,
即一次對某個對象加鎖可以保證對於多個事務都有效.

SQL標準考慮的並行事務之間需要避免的現象是什麼

共3個:

  1. 髒讀

  2. 不可重複讀

  3. 幻讀

髒讀: 一個事務讀取了另一個未提交的並行事務寫的數據.

不可重複讀: 一個事務重新讀取前面讀取過的數據,
發現該數據已經被另一個已提交的事務修改過.

幻讀: 一個事務重新執行了一個查詢, 返回一套符合查詢條件的數據,
發現這些數據因爲其他最近提交的事務而發生了改變.

備註: 實際上幻讀可以算是”不可重複讀”的一種子情況.
上面所述的”不可重複讀”算是下面所述的”虛讀”.

不可重複讀(Non-repeatable
Reads):一個事務對同一行數據重複讀取兩次,但是卻得到了不同的結果。

包括以下情況:

(1)虛讀:事務T1讀取某一數據後,事務T2對其做了修改,當事務T1再次讀該數據時得到與前一次不同的值。

(2) 幻讀(Phantom Reads):事務在操作過程中進行兩次查詢,第二次查詢的結果包含了第一次查詢中未出現的數據或者缺少了第一次查詢中出現的數據(這裏並不要求兩次查詢的SQL語句相同)。這是因爲在兩次查詢過程中有另外一個事務插入數據造成的。

如何理解SQL的可重複讀和幻讀之間的區別

https://zhidao.baidu.com/question/1498699183609661299.html

不可重複讀與幻讀比較相似,都是在一個事務中多次讀取到不同的數據。網絡上的總結如下
不可重複讀:所謂的虛讀,也就是大家經常說的不可重複讀,是指在數據庫訪問中,一個事務範圍內兩個相同的查詢卻返回了不同數據。這是由於查詢時系統中其他事務修改的提交而引起的。比如事務T1讀取某一數據,事務T2讀取並修改了該數據,T1爲了對讀取值進行檢驗而再次讀取該數據,便得到了不同的結果。
一種更易理解的說法是:在一個事務內,多次讀同一個數據。在這個事務還沒有結束時,另
一個事務也訪問該同一數據。那麼,在第一個事務的兩次讀數據之間。由於第二個事務的修改,那麼第一個事務讀到的數據可能不一樣,這樣就發生了在一個事務內
兩次讀到的數據是不一樣的,因此稱爲不可重複讀,即原始讀取不可重複。
所謂幻讀,是指事務A讀取與搜索條件相匹配的若干行。事務B以插入或刪除行等方式來修改事務A的結果集,然後再提交。
幻讀是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,比如這種修改涉及到表中的“全部數據行”。同時,第二個事務也
修改這個表中的數據,這種修改是向表中插入“一行新數據”。那麼,以後就會發生操作第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺一
樣.一般解決幻讀的方法是增加範圍鎖RangeS,鎖定檢鎖範圍爲只讀,這樣就避免了幻讀。簡單來說,幻讀是由插入或者刪除引起的。
大致的區別在於不可重複讀是由於另一個事務對數據的更改所造成的,而幻讀是由於另一個事務插入或刪除引起的

爲什麼數據庫中要提供”事務隔離級別”這個概念

在數據庫中, 爲了有效保證併發讀取數據庫的正確性, 提出的”事務隔離級別”.

參考:

https://baike.baidu.com/item/事務隔離級別/2638091?fr=aladdin

爲了避免上面出現的幾種情況,在標準SQL規範中,定義了4個事務隔離級別,不同的隔離級別對事務的處理不同。

未授權讀取

也稱爲讀未提交(Read
Uncommitted):允許髒讀取,但不允許更新丟失。如果一個事務已經開始寫數據,則另外一個事務則不允許同時進行寫操作,但允許其他事務讀此行數據。該隔離級別可以通過“排他寫鎖”實現。

授權讀取

也稱爲讀提交(Read
Committed):允許不可重複讀取,但不允許髒讀取。這可以通過“瞬間共享讀鎖”和“排他寫鎖”實現。讀取數據的事務允許其他事務繼續訪問該行數據,但是未提交的寫事務將會禁止其他事務訪問該行。

可重複讀取(Repeatable Read)

可重複讀取(Repeatable
Read):禁止不可重複讀取和髒讀取,但是有時可能出現幻讀數據。這可以通過“共享讀鎖”和“排他寫鎖”實現。讀取數據的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。

序列化(Serializable)

序列化(Serializable):提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接着一個地執行,不能併發執行。僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的數據不會被剛執行查詢操作的事務訪問到。

隔離級別越高,越能保證數據的完整性和一致性,但是對併發性能的影響也越大。對於多數應用程序,可以優先考慮把數據庫系統的隔離級別設爲Read
Committed
。它能夠避免髒讀取,而且具有較好的併發性能。儘管它會導致不可重複讀、幻讀和第二類丟失更新這些併發問題,在可能出現這類問題的個別場合,可以由應用程序採用悲觀鎖樂觀鎖來控制。

簡介一下樂觀鎖和悲觀鎖

樂觀鎖機制採取了更加寬鬆的加鎖機制。悲觀鎖大多數情況下依靠數據庫的鎖機制實現,以保證操作最大程度的獨佔性。但隨之而來的就是數據庫
性能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受。相對悲觀鎖而言,樂觀鎖更傾向於開發運用。

悲觀鎖,正如其名,具有強烈的獨佔和排他特性。它指的是對數據被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度,因此,在整個數據處理過程中,將數據處於鎖定狀態。悲觀鎖的實現,往往依靠數據庫提供的鎖機制(也只有數據庫層提供的鎖機制才能真正保證數據訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改數據)

SQL標準定義的事務隔離級別有哪些

共4個:

  1. 讀未提交

  2. 讀已提交

  3. 可重複讀

  4. 可串行化

在這裏插入圖片描述

注意: SQL定義的這4種隔離級別, 只定義了哪種現象不能發生,
但沒有定義哪種現象一定發生.

PG中事務隔離級別最小實體是什麼

在PG系統中, 事務的隔離級別所涉及的最小實體是元組, 即: Tuple.

所以對元組的操作(例如讀取, 插入, 更新, 刪除)需要實施訪問控制,
它們是通過鎖操作以及MVCC相關的操作來實現的.

7.7 PG中的三種鎖

PG有幾種鎖, 簡單介紹一下

共3種:

  1. SpinLock

  2. LWLock

  3. RegularLock

SpinLock的特點是: 封鎖時間很短, 沒有等待隊列和死鎖檢測機制,
事務結束時不能自動釋放SpinLock.

作爲一種最底層的鎖, 一般不直接使用SpinLock, 而是利用它來實現其他鎖(LWLock).

LWLock(輕量級鎖): 主要提供對共享存儲器的數據結構的互斥訪問.

LWLock有2種鎖模式: 1) 排他模式 2) 共享模式.

LWLock不提供死鎖檢測, 但在elog恢復期間被自動釋放,
所以持有輕量級鎖的期間調用elog發出錯誤信息不會出現輕量級鎖未釋放的問題.

LWLock的特點是: 有等待隊列, 無死鎖檢測, 能自動釋放鎖.

RegularLock就是一般數據庫事務管理中所指的鎖, 也簡稱爲Lock.

RegularLock由LWLock實現, 其特點是: 有等待隊列, 有死鎖檢測, 能自動釋放鎖.

7.8 鎖管理機制

PG都有哪些粒度的鎖, 鎖的對象分別是誰

5種:

  1. 表粒度的鎖

  2. 頁粒度的鎖

  3. 元組粒度的鎖

  4. 事務粒度的鎖

  5. 一般對象的鎖

表粒度的鎖操作表示在數據庫系統中加鎖對象爲一個表.

頁粒度的鎖操作表示在數據庫系統中加鎖 對象爲一個頁面.

元組….對象爲一個元組.

事務粒度…對象爲一個事務.

一般對象…對象爲一般對象.

各個粒度的鎖操作具體是怎樣的
表粒度的鎖操作
頁粒度的鎖操作
元組粒度的鎖操作
事務粒度的鎖操作
一般對象的鎖操作

7.9 死鎖處理機制

死鎖處理機制

在這裏插入圖片描述

死鎖處理相關操作

在PG中, 當進程不能獲得鎖進入等待隊列時, 就會觸發死鎖檢測的操作.

如果發現了”死鎖”, 進而嘗試進行死鎖的解除操作,
死鎖解除採用枚舉的方法嘗試調整隊列中進程的等待先後拓撲順序,
試圖找到一種打破進程之間循環等待的狀態.

7.10 多版本併發控制

MVCC 多版本併發控制

PG爲開發者提供了豐富的管理數據庫併發訪問的工具. 在內部,
PG利用MVCC來維護數據的一致性.

這就意味着當檢索數據時, 每個事務看到的只是一段時間之前的數據快照,
而不是數據庫的當前狀態(即: 最新的狀態).

這樣, 如果對數據庫會話進行事務隔離,
就可以避免一個事務看到其他併發事務的更新而導致不一致的數據.

優點: 使用MVCC的主要優點是對檢索(讀取)數據的鎖請求與寫數據的鎖請求並不衝突,
所以讀不會阻塞寫, 而寫也從不阻塞讀. 這就極大地提升了併發處理能力.

在這裏插入圖片描述

7.11 日誌管理

PG的日誌管理是怎樣的

日誌的必要性

日誌是數據庫系統必不可少的一部分, 它以一種安全的方式記錄數據庫變更的歷史.

當系統出現故障後, 數據庫系統通過使用日誌來重建對數據庫所做更新的過程,
以恢復數據庫到一致狀態, 從而保證數據庫的一致性和完整性.

PG的日誌主要有哪些

4個:

  1. XLOG 事務日誌

  2. CLOG 提交日誌

  3. SUBTRANS (子事務日誌)

  4. MULTIXACT(組合事務日誌)

已經有XLOG, 爲什麼還要CLOG呢

XLOG是一般的日誌記錄, 即通常意義上所認識的(數據庫事務)日誌記錄,
它記錄了事務對數據庫更新的過程和事務的最終狀態.

CLOG在一般的數據庫教材上是沒有提及的, 其實CLOG是XLOG的一種輔助形式,
記錄了事務的最終狀態. 因爲每一條XLOG日誌記錄相對較大,
如果需要通過日誌判斷一個事務的狀態, 那麼使用CLOG比使用XLOG要高效的多.

同時CLOG佔用的空間也非常有限.

此外, 爲支持嵌套事務, PG還引入了SUBTRANS日誌記錄----即子事務日誌,
記錄每個事務的父事務的事務ID, 這樣通過一個事務可以遞歸查找到其父事務,
但是並不能通過一個事務查找到其子事務.

同時, 爲了支持多版本併發控制, PG引入了組合事務ID(MultiXactID),
記錄事務的組合關係, 並維持從衆多事務ID到MultiXactId的映射關係.

爲什麼要設立日誌緩衝區

在PG中, 日誌通過日誌文件來存放. 如果每個日誌記錄在創建時都被立即寫到磁盤上,
那麼將增加大量的I/O開銷. 因爲通常向磁盤的寫入是以(數據)塊爲單位進行的,
而在大多數情況下, 一個日誌記錄比一個塊小得多, 爲了降低寫入日誌帶來的I/O開銷,
數據庫系統在實現時往往設置了日誌緩衝區, 即先將日誌記錄寫到主存中的日誌緩衝區中,
當日志緩衝區滿了以後以塊爲單位向磁盤寫出.

PG中數據庫系統直接操作磁盤的日誌文件嗎

否.

在數據庫系統中,
日誌緩衝區通過日誌管理器來管理.數據庫系統並不直接操作磁盤日誌文件,
一般是通過日誌緩衝區來使用日誌文件,
而緩衝區和磁盤之間的交互,同步則由日誌管理器來完成.

PG有四種日誌管理器, 即XLOG(事務日誌), CLOG(事務提交日誌),
SUBTRANS(子事務日誌)以及MULTIXACT(組合事務日誌).

PG是如何管理這些日誌的

PG通過一種緩衝區來實現對CLOG日誌, SUBTRANS日誌以及MULTIXACT日誌的管理,
即SLRU緩衝池----採用簡單LRU(Last Recently Used)算法作爲頁面轉換算法的緩衝池.

若要獲取一個事務狀態,直接通過日誌管理器操作日誌緩衝池嗎

不是.

如果要獲取一個事務的狀態, 並不是直接通過日誌管理器操作日誌緩衝池,
而是要通過事務日誌接口例程(Routes)進行操作.

簡介日誌的資源管理器作用

由於使用日誌的資源有很多種, PG爲對日誌進行分類,
使用了資源管理器(不是第3章中介紹的資源跟蹤器)的概念.
資源管理器主要用於在日誌系統中把各種需要記錄的數據分類,
通在日誌中標識資源管理號, 使系統在恢復或者讀取日誌記錄時,
能夠很方便的知道該日誌記錄的元數據屬於哪一類,
從而通過資源管理器的方法可以準確的選擇對應的方法.

7.11.1 SLRU緩衝池

SLRU緩衝區

在這裏插入圖片描述

7.11.2 CLOG日誌管理器 **

CLOG日誌管理器概述

CLOG日誌記錄的是事務的最終狀態. CLOG日誌管理器管理着CLOG日誌緩衝池,
該日誌緩衝池是基於SLRU緩衝池實現的.

CLOG日誌管理器模塊有哪些主要內容

共2塊:

  1. CLOG日誌管理器相關數據結構

  2. CLOG日誌管理器主要操作

7.11.3 SUBTRANS日誌管理器

7.11.4 MULTIXACT日誌管理器

7.11.5 XLOG日誌管理器

XLOG日誌概述

XLOG是傳統數據庫理論中提到的事務日誌, 它詳細地記錄了服務進程對數據庫的操作過程.

XLOG在內存中是如何存放的

XLOG日誌文件在內存中按頁進行存放, 每個頁面大小爲8KB, 每個頁都有一個頭部,
頭部信息之後纔是XLOG日誌記錄.

XLOG文件在物理磁盤中是如何存放的

每個XLOG文件都有一個ID, 但事實上它被分爲一個個大小爲16MB的XLOG段文件來存放.

如何在磁盤目錄中唯一的確定XLOG單文件

XLOG文件號和段文件號可以用來唯一的確定這個段文件.

如何確定XLOG日誌文件內的一個日誌記錄的地址

確定日誌文件內一個日誌記錄的地址時,
只需用一個XLOG文件號和日誌記錄在該文件內人偏移量即可.

XLOG日誌管理器模塊有哪些主要內容

共3個:

  1. XLOG日誌管理器相關數據結構

  2. XLOG日誌管理器主要操作

  3. XLOG日誌恢復策略

1 XLOG日誌管理器相關數據結構
PG日誌是REDO還是UNDO日誌

PG只使用REDO方法來進行數據庫的恢復,
它不使用UNDO是因爲其數據的多版本使得UNDO沒有必要.

但從本質上講, PG日誌並非REDO日誌, 而應該是UNDO/REDO日誌,
其創建檢查點時大體上服務UNDO/REDO日誌創建檢查點時要服從的規則, 只是做了一點改動.

參考: 淺析MySQL事務中的redo與undo

https://www.jianshu.com/p/20e10ed721d0

2 XLOG日誌管理器主要操作
XLOG日誌管理器操作分幾個組成

XLOG日誌管理器的操作由以下幾個部分組成:

  1. 日誌文件的建立

  2. 初始化

  3. 啓動操作

  4. 日誌的插入

  5. 日誌的歸檔

  6. 日誌的刪除

  7. 日誌文件的恢復

  8. 日誌備份塊的讀取

  9. 日誌的REDO操作

3 XLOG日誌恢復策略
XLOG日誌恢復策略概述

在PG中, 系統在崩潰後重新啓動時會調用StartupXlog入口函數,
該函數首先會掃描全局信息控制文件(global/pg_control)讀取系統的控制信息,
然後掃描XLOG日誌目錄結構檢測其是否完整,進而讀取到最新的日誌檢查點記錄,接下來根據日誌記錄序列的偏序關係檢測到系統是否處理非正常狀態下,
若系統處於非正常狀態,
則觸發恢復機制進行恢復.恢復完成後重新建立檢查點並初始化XlogCtl控制信息,
然後啓動事務提交日誌以及相關輔助日誌模塊.

日誌中出現哪幾種情況時需要進行恢復操作

日誌中出現以下三種情況需要進行恢復操作:

  1. 日誌文件中掃描到back_label文件.

  2. 根據ControlFile記錄的最新檢查點讀取不到日誌記錄.

  3. 根據ControlFile記錄的檢查點與通過該記錄找到的檢查點日誌中的Redo位置不一致.

日誌恢復的具體步驟有哪些

在PG系統中, 日誌建立的策略是採用改進的非靜止檢查點的Redo日誌,
恢復則是找到最近的合法檢查點然後做Redo操作. 恢復操作的具步驟如下:

  1. 首先更新控制信息到ControFile中.

  2. 初始化日誌恢復時所用到的資源管理器.

  3. 從檢查點日誌記錄的REDO位置開始往後讀取日誌記錄.

  4. 根據日誌記錄的資源管理器號選擇對應的RMGR,
    然後利用該RMGR做日誌記錄中所記錄的操作過程(REDO操作).

  5. 重複步驟3和4的過程, 直至讀取不到日誌記錄.

幾種典型的日誌的恢復操作介紹

在上述恢復流程中, 第4步的REDO操作會針對不同的日誌類型做不同的恢復操作.
下面介紹幾種典型日誌的恢復操作.

  1. Database類型的日誌操作.

  2. Heap類型的Redo操作.

  3. B-Tree類型的Redo操作.

  4. XLog類型的Redo操作.

恢復完成後都做了些什麼

當恢復過程完成後, 重新建立檢查點並重新初始化XlogCtl結構信息.
然後繼續調用;StartupCLOG函數,
StartupSUBTRANS函數和StartupMultiXact函數完成事務提交日誌及其他輔助日誌模塊的啓動.

如果根據系統日誌檢測到系統不需要恢復操作, 那麼將跳過恢復操作,
然後完成事務提交日誌等相關模塊的初始化.

7.11.6 日誌管理器總結 **

7.12 小結 **

如果我們把整個數據庫系統視爲一個團隊,
那麼事務系統在這個團隊中扮演了”指揮官”的角色,
它根據外部用戶命令以及系統內部狀態決定了當前數據庫系統中操作的執行方向.

在7.1節到7.5節中, 詳細闡述了PG事務管理器的操作,
其核心功能就是根據當前狀態和接收到的外部狀態(用戶命令)決定當前需要執行的操作,
所以它承擔了整個系統的決策功能, 是”指揮官”的大腦.

在7.6到7.10節中,
詳細闡述了PG的併發控制機制,其核心功能是爲了在保證數據一致性的前提下提高併發度,
所有它承擔了整個系統的調度協調功能, 是”指揮官”的節拍器.

在7.11節中, 詳細闡述國PG的日誌管理機制,
其核心功能是通過磁盤日誌文件夾來記錄數據庫操作狀態序列以及數據庫變化過程,
所以它承擔了整個系統的保障恢復功能.

總之, 事務系統串聯了整個數據庫中各個不同的模塊,
事務系統的調度決策驅動了整個數據庫系統的執行進程.

第9章 數據庫安全

附錄

oracle – 數據塊(data Block)

基本關係:數據庫—表空間—數據段—分區—數據塊

數據塊(data Block)
一、數據塊Block是Oracle存儲數據信息的最小單位。這裏說的是Oracle環境下的最小單位。Oracle也就是通過數據塊來屏蔽不同操作系統存儲結構的差異。無論是Windows環境,還是Unix/Linux環境,他們的操作系統存儲結構和方式、甚至字符排列的方式都是不同的。Oracle利用數據塊將這些差異加以屏蔽,全部數據操作採用對Oracle塊的操作,相當於是一個層次的抽象。

二、Oracle所有對數據的操作和空間分配,實際上都是針對數據塊Block的操作。我們從數據表中搜索出一行,實際中Oracle就會從內存緩衝區(或者硬盤)中讀取到該行所在的數據塊,再返回這數據塊上的指定數據行。Oracle無論是在緩衝區,還是在硬盤,進行數據操作的雖小單位也就是數據塊。

三、數據塊是有大小的,在一個數據庫建立的時候,通過參數進行設置。注意,在Oracle數據庫參數中,只有數據塊大小的參數是建庫之後不能進行修改的。數據塊的大小,在一個數據庫中可以支持多個,但是一般沒有太大的意義,會給管理和調試帶來一定的負擔。

四、數據塊(data block)的大小是操作系統的data
block的整數倍,ORACLE默認是8K,還有4K,16K,32k幾種。設置數據塊的大小是依據不同類型的系統的。如果數據塊設置比較大,那麼一次讀取的數據行較多,相應對SGA內存消耗比較大,特定查詢引發的換入換出可能較多。如果設置的過小,頻繁的IO邏輯物理讀也會引起性能問題。
-----相關參數爲db_block_size,查看block大小。

SQL\> **show parameter db_block_size;**  
NAME                                 TYPE        VALUE  
------------------------------------ ----------- ------------------------------  

db_block_size integer 8192 //1024×8
注:

1、DB_BLOCK_SIZE作爲數據庫的最小操作單位,是在創建數據庫的時候指定的,在創建完數據庫之後便不可修改。要修改DB_BLOCK_SIZE,需要重建數據庫。一般可以將數據EXP出來,然後重建數據庫,指定新的DB_BLOCK_SIZE,然後再將數據IMP進數據庫。
2、
DB_BLOCK_SIZE一般設置爲操作系統塊的倍數,即2K,4K,8K,16K或32K,但它的大小一般受數據庫用途的影響。對於聯機事務,其特點是事務量大,但每個事務處理的數據量小,所以DB_BLOCK_SIZE設置小點就足夠了,一般爲4K或者8K,設置太大話一次讀出的數據有部分是沒用的,會拖慢數據庫的讀寫時間,同時增加無必要的IO操作。而對於數據倉庫和ERP方面的應用,每個事務處理的數據量很大,所以DB_BLOCK_SIZE一般設置得比較大,一般爲8K,16K或者32K,此時如果DB_BLOCK_SIZE小的話,那麼I/O自然就多,消耗太大。
3、
大一點的DB_BLOCK_SIZE對索引的性能有一定的提高。因爲DB_BLOCK_SIZE比較大的話,一個DB_BLOCK一次能夠索引的行數就比較多。
4、
對於行比較大的話,比如一個DB_BLOCK放不下一行,數據庫在讀取數據的時候就需要進行行鏈接,從而影響讀取性能。此時DB_BLOCK_SIZE大一點的話就可以避免這種情況的發生。

初始化參數db_file_multiblock_read_count是用來約束Oracle進行多數據塊讀取時的行爲,所謂多數據塊讀取,就是Oracle在一次I/O時,可以讀取多個數據塊,從而用最小的I/O完成數據的讀取。
db_file_multiblock_read_count的設置要受OS最大IO能力影響,也就是說,如果你係統的硬件IO能力有限,即使設置再大的db_file_multiblock_read_count也是沒用的。
------初始化參數db_file_multiblock_read_count,查看一次I/O完成數據的讀取。

SQL\> show parameter db_file_multiblock_read_count;  
NAME                                 TYPE        VALUE  
-------------------------------------------------------  
db_file_multiblock_read_count        integer     32  
   
SQL\> alter session set db_file_multiblock_read_count=256;  
會話已更改。  
  
SQL\> show parameter db_file;  
NAME                                 TYPE        VALUE  
-----------------------------------------------------  
db_file_multiblock_read_count        integer      128

參考

oracle – 數據塊(dataBlock)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章