<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 問題出現 我們在線上巡檢中發現,一個實例的pg_xlog目錄,增長到4G,很是疑惑。剛開始懷疑是日志歸檔過慢,日志堆積在pg_xlog目錄下面,未被清除導致。于是檢查歸檔目錄下的文件,內容如下。但發現新近完成寫入的日志文件都被歸檔成功了(即在pg_xlog/archive_status里面,有對應的xxx.done文件)。 ~~~ ls -lrt pg_xlog ... -rw------- 1 xxxx xxxx 16777216 Jun 14 18:39 0000000100000035000000DE -rw------- 1 xxxx xxxx 16777216 Jun 14 18:39 0000000100000035000000DF drwx------ 2 xxxx xxxx 73728 Jun 14 18:39 archive_status -rw------- 1 xxxx xxxx 16777216 Jun 14 18:39 0000000100000035000000E0 ls -lrt pg_xlog/archive_status ... -rw------- 1 xxxx xxxx 0 Jun 14 18:39 0000000100000035000000DE.done -rw------- 1 xxxx xxxx 0 Jun 14 18:39 0000000100000035000000DF.done -rw------- 1 xxxx xxxx 0 Jun 14 18:39 0000000100000035000000E0.done ~~~ 仔細觀察,奇怪的是,pg_xlog里面還有一些日志文件,其文件名對應了還沒產生的日志號!如下所示,當前正在被寫入的日志號為100000035000000E0左右,卻出現了名為1000000360000000C的日志文件名,更蹊蹺的是,其修改時間還在很早以前,就是說不是新近創建或修改過的,如下面的文件修改或創建時間是在當前時間的一個小時之前: ~~~ ls -lrt pg_xlog .... -rw------- 1 xxxx xxxx 16777216 Jun 14 17:37 00000001000000360000000C -rw------- 1 xxxx xxxx 16777216 Jun 14 17:37 000000010000003600000014 .... ~~~ 這是怎么回事呢?難道是“幽靈日志”?下面我們要搞清楚兩個問題:1)為什么會出現”幽靈日志“?2)PG正常情況下日志空間大小是多少? ## PG日志創建清理機制 要回答上述問題,需要先摸清PG的日志創建、保持和清理機制。與此直接相關的模塊有:日志寫入(WAL writer)進程和日志歸檔(archiver)進程。其實檢查點(checkpointer)進程和日志發送進程(WAL sender)也與此有關。 WAL writer負責異步把WAL日志刷入磁盤;與此同時,其他普通后臺進程,也可能會同步的將WAL日志刷入磁盤,我們先從分析它們入手。從代碼里面不難看出,它們將日志寫入新的日志文件時,有如下函數調用: ~~~ XLogWrite -> XLogFileInit ->BasicOpenFile ~~~ BasicOpenFile負責打開一個新的日志文件,如果文件不存在,則新建文件。而其代碼注釋里面提到“Try to use existent file (checkpoint maker may have created it already)”,即打開的文件可能已經被checkpointer進程創建。 于是我們將目光轉向checkpointer。其主要函數CheckpointerMain的邏輯如下: 1. 檢查是否有checkpoint request信號; 2. 檢查是否checkpoint timeout時間已到; 3. 調用CreateCheckPoint做檢查點操作; 4. 調用WaitLatch等待checkpoint timeout或checkpoint request信號。 重點內容都在`CreateCheckPoint`函數中,其邏輯如下: 1. 檢查上次檢查點后是否有WAL日志寫入,如果沒有直接返回; 2. 調用CheckPointGuts將WAL日志fsync到磁盤;注意其中的CheckPointBuffers函數,會根據checkpoint_completion_target的值做一定的delay,使fsync操作的完成時間占兩個檢查點之間時間間隔的比例,約為checkpoint_completion_target; 3. 在WAL中插入檢查點日志信息; 4. 取系統前一次檢查點的日志位置指針,即此指針之前的日志文件,都可以刪除了; 5. 由KeepLogSeg根據wal_keep_segments和replication slot的情況計算要額外保留的日志; 6. 由RemoveOldXlogFiles做真正的日志刪除,而神奇的是RemoveOldXlogFiles并未實際刪除文件,而是將其回收,即將老文件rename成新文件,做了日志文件預分配; 7. 完成檢查點返回。 可以看到,在這里出現日志刪除、預分配等邏輯。也就是說PG的日志文件可能是在做檢查點操作時預分配的!預分配的文件名使用了“未來”的目前還不存在的日志號,這就解釋了我們之前遇到的“幽靈日志”情況,也回答了我們的第一個問題。 當然,需要說明的是,日志的保留和刪除還和是否被archiver進程歸檔成功有關。 ## 日志空間大小 繼續看第二個問題。前面提到的日志空間暴增讓我們如臨大敵,那么PG日志到底最多會占用多少空間?我們遇到的漲到3G情況正常嗎? 從日志清理邏輯(重點是`KeepLogSeg`和`RemoveOldXlogFiles`函數)的分析,我們得到下面的結論: 1. 日志的刪除和預分配只在檢查點剛完成時進行; 2. 刪除時,保證上一次檢查點之后到現在的日志不會被刪除; 3. 保證從目前日志位置往前wal_keep_segments個日志文件不會刪除; 4. 預分配的過程是,對所有不再需要的舊文件重命名為一個未來的日志號,直到預分配的文件數量達到XLOGfileslop,即`2*checkpoint\_segments + 1`。checkpoint_segments為一個可配置的參數,控制了兩個檢查點間產生的日志文件數量。 另外,為討論方便,下面我們先做如下假設: 1. 有足夠多(即大于2*checkpoint_segments + 1)的不再需要的舊日志文件,可以用于預分配; 2. 每次檢查點操作完成的時間,正好占兩個檢查點之間時間間隔的checkpoint_completion_target(線上目前我們設為0.9)。 設某次檢查點操作完成時的時間點為A,則此時做日志預分配的情形如下圖所示: ![檢查點完成時的日志預分配](https://box.kancloud.cn/2015-09-24_560398ec8afaf.png "檢查點完成時的日志預分配") 候選被回收的文件是在時間點C之前的、并且大于wal_keep_segments個文件間隔的文件;這些文件將重命名為預分配文件,文件號為從A對應的日志開始遞增,直到達到`2*checkpoint_segments + 1`個文件為止。 做檢查點操作過程中,是不斷產生新日志文件的,而且兩次檢查點之間的日志文件數為一個穩定的值,即checkpoint_segments。因此,在時間點B到A之間產生的日志數約為`checkpoint_segments * checkpoint_completion_target`。 待A時間點預分配完日志文件,并刪除其他不需要的日志后,新產生的日志將使用預分配空間,日志空間不會增大,日志空間大小達到一個穩定狀態。而此時日志的空間至少為:保留的日志空間 + 預分配空間 + 正在被寫入的那個文件,即為: ~~~ max(wal_keep_segments, checkpoint_segments + checkpoint_segments*checkpoint_completion_target) + 2 * checkpoint_segments + 1 + 1 ~~~ 這就是在日志大小達到穩定狀態時,所能達到的最大值。所謂“穩定狀態”是指,一旦達到這個狀態,優先使用預分配空間,一般不會增大;即使日志文件繼續增加,也會被刪除(如果archiver和wal sender都正常工作的話)。而日志大小也不會明顯減少,因為處于預分配狀態的日志數量、前一次檢查點到當前時間點的日志量都沒有大的變化。 回到我們的問題,PG的日志空間占用的正常值,可以用上面的公式計算出來。如果wal_keep_segments為80,checkpoint_segments為64,checkpoint_completion_target為0.9,那么根據公式計算結果為4.02G。即日志空間增加到4G也是正常的。并且可以通過減小checkpoint_segements的值,減少日志空間占用。 ## 幾個問題 通過上面分析得出的公式,我們在處理日志時遇到的一些問題就迎刃而解了,例如: Q: 增加wal_keep_segments會增大日志空間嗎? A: 如果增加wal_keep_segments后,其值仍小于(checkpoint_segments + checkpoint_segments * checkpoint_completion_target),則增加wal_keep_segments并不會增大日志占用空間。 Q: checkpoint_segments與日志空間大小有什么關系? A: 在wal_keep_segments較小時,checkpoint_segments對日志空間占用有至關重要的影響。日志空間大小基本上可以用4倍checkpoint_segments來估算出來。但當wal_keep_segments較大時,比如是checkpoint_segments的10倍,則checkpoint_segments對日志空間大小的影響相對就小很多了。 ## 思考題 上面的分析中,我們做了兩點假設。一個是系統中有足夠多的舊日志可供回收,這種情況會出現嗎(提示:archiver進程或replication slot對日志刪除的影響)?另一個是,檢查點操作會及時完成,那么如果檢查點操作未及時完成,會出現什么情況?會導致日志空間占用比我們的公式更大嗎?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看