<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                PostgreSQL 9.4 已于2014年底正式發布了(阿里云的RDS將支持PG 9.4)。在這個版本,我們看到了像Jsonb, Logical Decoding, Replication Slot等新功能。對于Replication Slot,文檔上介紹的不多,乍一看讓人比較難理解是做什么的。其實,Replication Slot的出現,主要是為最終在PG內核實現邏輯復制和雙向復制鋪路的(目前,邏輯和雙向復制在內核中還缺少很多核心功能點,需要借助BDR插件,見[PG官方wiki](https://wiki.postgresql.org/wiki/BDR_Project)?,引入Replication Slot的背后原因見[這里](http://blog.2ndquadrant.com/postgresql-9-4-slots/))。不過,作為9.4版本的一個主要功能,它不但可以用于邏輯復制,還可用于物理復制(或者叫Streaming Replication)。針對物理復制的Replication Slot稱為Physical Replication Slot。 由于大家目前主要用的還只是PG自帶的物理復制方式,我們就重點分析一下Physical Replication Slot。 使用Physical Replication Slot,可以達到兩個效果: A)可以確保從庫(standby)需要的日志不被過早備份出去而導致從庫失敗,出現下面的error: ~~~ ERROR: requested WAL segment 00000001000000010000002D has already been removed ~~~ 通過Replication Slot記錄的從庫狀態,PG會保證從庫還沒有apply的日志,不會從主庫的日志目錄里面清除或archive掉。而且,replication slot的狀態信息是持久化保存的,即便從庫斷掉或主庫重啟,這些信息仍然不會丟掉或失效。 B)當允許應用連接從庫做只讀查詢時,Replication Slot可以與運行時參數hot_standby_feedback配合使用,使主庫的vacuum操作不會過早的清掉從庫查詢需要的記錄,而出現如下錯誤(錯誤的原因下面會詳細解釋): ~~~ ERROR: canceling statement due to conflict with recovery ~~~ 下面看看Physical Replication Slot的用法和內核實現。 **用法** 下面是啟用Replication Slot的步驟,很簡單: 1)首先需要配置好Steaming Replication的主庫從庫。涉及的參數有,listen_addresses(='*'),hot_standby(=on), wal_level(=hot_standby),max_wal_senders(=1),尤其注意配置max_replication_slots大于等于1。這些參數主從庫應一致。 2)在主庫創建replication slot: ~~~ postgres=# SELECT * FROM pg_create_physical_replication_slot('my_rep_slot_1'); slot_name | xlog_position ---------------+--------------- my_rep_slot_1 | ~~~ 此時replication slot還不處于active狀態。 3) 在從庫配置recovery.conf如下,然后重啟從庫: ~~~ standby_mode = 'on' primary_slot_name = 'my_rep_slot_1' primary_conninfo = 'user=pg001 host=10.x.x.x port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres' ~~~ 4)觀察主庫replication slot的狀態變化: ~~~ postgres=# SELECT * FROM pg_replication_slots?; slot_name | plugin | slot_type | datoid | database | active | xmin | catalog_xmin | restart_lsn ---------------+--------+-----------+--------+----------+--------+------+--------------+------------- my_rep_slot_1 | | physical | | | t | 1812 | | 0/3011A70 ~~~ 5)與hot_standby_feedback配合使用。在將從庫的postgresql.conf文件中的hot_standby_feedback選項設為on,重啟從庫即可。 **內核實現** replication slot是由下面的[patch](http://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=858ec11858a914d4c380971985709b6d6b7dd6fc)加入內核中的: ~~~ author Robert Haas <rhaas@postgresql.org> Sat, 1 Feb 2014 03:45:17 +0000 (22:45 -0500) committer Robert Haas <rhaas@postgresql.org> Sat, 1 Feb 2014 03:45:36 +0000 (22:45 -0500) Replication slots are a crash-safe data structure which can be created on either a master or a standby to prevent premature removal of write-ahead log segments needed by a standby, as well as (with hot_standby_feedback=on) pruning of tuples whose removal would cause replication conflicts. Slots have some advantages over existing techniques, as explained in the documentation. ~~~ 這個patch改的文件不少,分析這些代碼,我們重點關注下面的問題: A)Replication Slot是如何在內核中創建的? 通過分析創建Replication Slot時調用的函數ReplicationSlotCreate,可以看出,**Replication Slot實質上是內存中的一些數據結構,加上持久化保存到pg_replslot/目錄中的二進制狀態文件。**在PG啟動的時候,預先在共享內存中分配好這些數據結構所用內存(即一個大小為max_replication_slots的數組)。這些數據結構在用戶創建Replication Slot時開始被使用。一個Replication Slot被創建并使用后,其數據結構和狀態文件會被WAL(Write-Ahead-Log)的發送者(wal_sender)進程更新。 另外,如果單純從Replication Slot的名字,我們很容易覺得Replication Slot會創建新的與從庫的連接,進行日志發送。實際上,創建過程中并沒有創建新的與從庫的連接,Replication Slot還是使用了wal_sender原有連接(由于一個從庫一個wal_sender連接,所以一個從庫和主庫之間也只有一個active的Replication Slot)。 B) Replication Slot的狀態是如何被更新的? 很容易發現,Replication Slot的狀態的更新有兩種情況。 第一種是在ProcessStandbyHSFeedbackMessage這個函數被更新。這個函數是在處理wal_sender所收到的從庫發回的feedback reply message時調用的。通過這個函數,我們可以看出,每個wal_sender進程的Replication Slot(就是用戶創建的Replication Slot)保存在MyReplicationSlot這個全局變量中。在處理從庫發回的reply時,reply中的xmin信息會被提取出來,存入slot的data.xmin和effective_xmin域中,并通過函數ProcArraySetReplicationSlotXmin,最終更新到系統全局的procArray->replication_slot_xmin結構中(以使其對所有進程可見),完成slot的更新。 這里要注意,如果我們有多個Replication Slot(分別對應各自從庫),則在更新全局結構procArray->replication_slot_xmin時,會選取所有slot中最小的xmin值。 第二種是在ProcessStandbyReplyMessage中。這個函數處理從庫發送的restart lsn信息(即從庫apply的日志的編號),會直接將其更新到replication slot的restart lsn域中,并保存到磁盤,用于主庫判斷是否要保留日志不被archive。 C) Replication Slot如何和hot_standby_feedback配合,來避免從庫的查詢沖突的? 這里,從庫的查詢沖突指的是下面的情況:從庫上有正在運行的查詢,而且運行時間很長;這時主庫上在做正常的vaccum,清除掉無用的記錄版本。但主庫的vaccum是不知道從庫的查詢存在的,所以在清除時,不考慮從庫的正在運行的查詢,只考慮主庫里面的事務狀態。其結果,vacuum可能會清除掉從庫查詢中涉及的,仍然在使用的記錄版本。當這些vaccum操作,通過日志同步到從庫,而恰好從庫的查詢仍然沒有運行完,vaccum就要等待或cancel這個查詢,以保證同步正常繼續和查詢不出現錯誤的結果。這樣,每當用戶在從庫運行長查詢,就容易出現我們上面提到到query conflict error。 如何避免這種沖突呢?目前最好的解決方案是使用hot_standby_feedback + Replication Slot。其原理簡單說就是,從庫將它的查詢所依賴的記錄版本的信息,以一個事務id來表示,并放在從庫發回給主庫wal_sender的reply中發給主庫(見函數XLogWalRcvSendHSFeedback),并最終傳導給主庫vaccum,讓其刀下留人,暫時不清除相關記錄。 具體過程是,在從庫,函數XLogWalRcvSendHSFeedback調用GetOldestXmin獲得xmin,放入給主庫的reply中。主庫的wal_sender收到后,如果使用了Replication Slot,就把這個xmin放入slot的狀態信息中,并更新此時系統所有slot的最小xmin。這個系統所有slot的最小xmin怎么在主庫傳導給vacuum的呢?以自動觸發的vacuum操作為例,其中的邏輯的順序如下: GetSnapshotData(vacuum事務開始時,獲取slot xmin,存入全局變量) ->vacuum_set_xid_limits(調用 GetOldestXmin,通過全局變量,獲取系統xmin和slot xmin,取較小值)-> vacuum_lazy (使用xmin,判斷哪些記錄版本可以清除) 這樣,利用Replication Slot這個渠道,就解決了從庫查詢沖突。 **注意事項** 最后,介紹一下使用Replication Slot的注意事項: 1)如果收不到從庫的reply,Replication Slot的狀態restart lsn會保持不變,造成主庫會一直保留本地日志,可能導致日志磁盤滿。所以應該實時監控日志磁盤使用情況,并設置較小的wal_sender_timeout,及早發現從庫斷掉的情況。 2)將hot_standby_feedback設為on時,注意如果從庫長時間有慢查詢發生,可能導致發回到主庫的xmin變化較慢,主庫的vaccum操作停滯,造成主庫被頻繁更新的表大小暴增。 除了物理復制,Replication Slot對邏輯復制的意義更大,我們期待在可能出現邏輯復制功能的9.5版本中看到它大顯身手。
                  <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>

                              哎呀哎呀视频在线观看