婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 淺談PostgreSQL中的孤兒文件用法(orphaned data files)

淺談PostgreSQL中的孤兒文件用法(orphaned data files)

熱門標簽:400電話申請客服 江蘇400電話辦理官方 電銷機器人能補救房產中介嗎 地圖標注要花多少錢 廣州電銷機器人公司招聘 移動外呼系統模擬題 天津開發區地圖標注app 電話機器人怎么換人工座席 濟南外呼網絡電話線路

創建一個測試表

postgres=# create table t1(a int);
CREATE TABLE
postgres=# select pg_relation_filepath('t1');
 pg_relation_filepath
----------------------
 base/75062/75297
(1 row) 
postgres=#

在操作系統上已經可以看到該文件。

$ ls -la $PGDATA/base/75062/75297
-rw------- 1 postgres postgres 0 Nov 9 11:11 /data/pgdata/11/data/base/75062/75297

插入一些數據:

postgres=# show segment_size;
 segment_size
--------------
 1GB
(1 row)
postgres=# insert into t1 select * from generate_series(1,100000000);
INSERT 0 100000000
postgres=#

因為segment_size的設置為1GB,磁盤上已經有了多個文件

$ ls -la $PGDATA/base/75062/75297*
-rw------- 1 postgres postgres 1073741824 Nov 9 11:19 /data/pgdata/11/data/base/75062/75297
-rw------- 1 postgres postgres 1073741824 Nov 9 11:17 /data/pgdata/11/data/base/75062/75297.1
-rw------- 1 postgres postgres 1073741824 Nov 9 11:18 /data/pgdata/11/data/base/75062/75297.2
-rw------- 1 postgres postgres 439803904 Nov 9 11:19 /data/pgdata/11/data/base/75062/75297.3
-rw------- 1 postgres postgres  917504 Nov 9 11:18 /data/pgdata/11/data/base/75062/75297_fsm

現在,開啟另一個會話(session 2)。

在session2中,啟動一個事務并創建一個空表,但是不提交事務:

postgres=# begin;
BEGIN
postgres=# create table t2(a int);
CREATE TABLE
postgres=# select pg_relation_filepath('t2');
 pg_relation_filepath
----------------------
 base/75062/75300
(1 row)
 
postgres=# select * from pg_backend_pid();
 pg_backend_pid
----------------
   17710
(1 row) 
postgres=#

在操作系統已經可以看到對應的文件:

$ ls -la $PGDATA/base/75062/75300
-rw------- 1 postgres postgres 0 Nov 9 11:23 /data/pgdata/11/data/base/75062/75300

如果這個時候,posrgresql server發生了奔潰、或者發生了oom被kill了或者session被kill了。會發生什么呢?

我們來模擬一下session被kill的場景:

$ kill -9 17710

再次在session2中執行查詢:

postgres=# select 1;
server closed the connection unexpectedly
  This probably means the server terminated abnormally
  before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.
postgres=#

這個session在事務提交之前被kill了,事務無法正常完成,但是事務已經創建了一個表。應該發生什么呢?事務被回滾,創建的表應該不存在了。

postgres=# select * from t2;
ERROR: relation "t2" does not exist
LINE 1: select * from t2;
      ^
postgres=#

這正是我們所預期的。但在操作系統上,文件仍然存在:

$ ls -la $PGDATA/base/75062/75300
-rw------- 1 postgres postgres 0 Nov 9 11:23 /data/pgdata/11/data/base/75062/75300

這樣,文件就成了孤兒文件(orphaned file)。

postgresql并不知道這個文件屬于哪個relation

postgres=# select relname from pg_class where oid = '75300';
 relname
---------
(0 rows) 
postgres=#

這樣,你就需要自己手動清理孤兒文件了!

假設你做了大量的數據的加載,就在加載完成之前,會話被殺死:

postgres=# begin;
BEGIN
postgres=# create table t3(a int);
CREATE TABLE
postgres=# select pg_relation_filepath('t3');
 pg_relation_filepath
----------------------
 base/75062/99528
(1 row)
 
postgres=# select * from pg_backend_pid();
 pg_backend_pid
----------------
   21988
(1 row)
 
postgres=# insert into t3 select * from generate_series(1,1000000000);
server closed the connection unexpectedly
  This probably means the server terminated abnormally
  before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.

雖然會話被kill了。但是磁盤上的空間并沒有被釋放。

$ ls -la $PGDATA/base/75062/99528*
-rw------- 1 postgres postgres 1073741824 Nov 9 11:51 /data/pgdata/11/data/base/75062/99528
-rw------- 1 postgres postgres 413777920 Nov 9 11:51 /data/pgdata/11/data/base/75062/99528.1
-rw------- 1 postgres postgres  385024 Nov 9 11:51 /data/pgdata/11/data/base/75062/99528_fsm

在最糟糕的時候,可能會占用大量的磁盤空間。那是否有什么方法去檢測這些孤兒文件呢?

你需要比較postgresql中的目錄表中的記錄和文件系統上信息,然后刪除這些孤兒文件。這個過程需要小心謹慎。

首先獲得你要檢測的數據庫的oid:

postgres=# select oid from pg_database where datname = 'postgres';
 oid 
-------
 75062
(1 row) 
postgres=#

這樣就可以知道文件在文件系統上的位置。即 $PGDATA/base/[OID_OF_THE_DATABASE]

然后,獲得孤兒文件:

postgres=# select * from pg_ls_dir ( '/data/pgdata/11/data/base/75062' ) as file where file ~ '^[0-9]*$' and file::text not in (select oid::text from pg_class );
 file 
-------
 75280
 75281
 75282
 75283
 75300
 83144
 99528
(7 rows) 
postgres=#

補充:理解postgreSQL中的prepared transactions和處理孤兒(orphans)事務

Prepared transactions是PostgreSQL的一個關鍵特性。理解該特性提供的功能和處理任何潛在的陷阱對于系統的維護是很關鍵的。所以,我們來深入研究一下具體什么是prepared transactions。

關于事務

在數據庫系統中,事務是一種處理通常包含多個語句的塊中的全部或零個語句的方法。在提交整個塊之前,該塊中語句的結果對其他事務不可見。 如果事務失敗或回滾,則對數據庫完全沒有影響。

事務依附于會話。但是,當要執行與會話獨立的事務時(也有其他好處)。這就是“prepared transactions”的來源。

prepared transactions

prepared transaction是獨立于會話、抗崩潰、狀態維護的事務。事務的狀態存儲在磁盤上,這使得數據庫服務器即使在從崩潰中重新啟動后也可以恢復事務。在對prepared transaction執行回滾或提交操作之前,將一直維護該事務。

PostgreSQL文檔聲明,在一個已存在的事務塊中,可以使用prepare transaction 'transaction_id‘命令創建一個prepared transaction。它進一步聲明該過程為兩階段提交準備了一個事務。

此外,建議應用程序或交互式會話不要使用prepared transaction。理想情況下,外部事務管理器應該跨同構或異構數據庫資源執行原子的全局事務。

在postgreSQL中,缺省的max_prepared_transaction=0;即關閉了prepared transaction。如果你想使用prepared transaction,建議將max_prepared_transaction設置成max_connections的值。在同步的流復制standby庫上,最好將其設置的比max_connections大一點,以免standby不能接收查詢。

在任何給定的時間,你可以查看活躍狀態的prepared transactions,通過查看視圖pg_prepared_xacts。

pg_prepared_xacts視圖含有以下一些列:

#select * from pg_prepared_xacts;
 transaction | gid | prepared | owner | database
-------------+-----+----------+-------+----------
(0 rows)

1.transaction:事務id

2.gid:用戶為prepared transaction定義的名稱

3.prepared:prepared日期,創建事務時帶有時區的時間戳

4.owner:創建該prepared transaction的事務

5.database:數據庫名

創建prepared transaction

知道什么是prepared transaction之后,現在來看看如何創建一個prepared transaction。創建一個該事務通常需要四個步驟:

1.begin(或start transaction)

2.執行需要的操作

3.prepare transaction

4.commit(或rollback prepared)

prepare transaction、commit prepared、或rollback prepared后面加上一個gid,可以唯一標識prepared transaction。

例如下面的代碼塊:

postgres=# begin;
BEGIN
postgres=# create table abce(id int);
CREATE TABLE
postgres=# insert into abce values(1);
INSERT 0 1
postgres=# prepare transaction 'abce_insert';
PREPARE TRANSACTION
postgres=# select * from pg_prepared_xacts;
 transaction |  gid  |   prepared   | owner | database
-------------+-------------+-------------------------------+----------+----------
  16362 | abce_insert | 2020-12-09 11:41:45.742375+08 | postgres | postgres
(1 row)
 
postgres=# commit prepared 'abce_insert';
COMMIT PREPARED
postgres=# select * from pg_prepared_xacts;
 transaction | gid | prepared | owner | database
-------------+-----+----------+-------+----------
(0 rows)
 
postgres=#

當一個含有一個或多個活躍的prepared transactions的postgresql停止了或者奔潰了,會為每個活躍的prepared transaction創建一個文件,在目錄pg_twophase中。

比如,我們有個prepared transaction:

postgres=# select * from pg_prepared_xacts;
 transaction |  gid  |   prepared   | owner | database
-------------+--------------+-------------------------------+----------+----------
  16363 | abce_insert2 | 2020-12-09 11:46:01.983483+08 | postgres | postgres
(1 row)
 
postgres=#

所以我沒有提交事務就停止了postgresql server。postgresql就會創建一個名為00003FEB的文件,對應于prepared transaction的事務id。

$ ls -l ../data/pg_twophase/
total 4
-rw------- 1 postgres postgres 220 Dec 9 11:47 00003FEB

00003FEB等價于16363。在postgresql被重啟后,在啟動日志會報如下信息:

2020-12-09 11:51:28.112 CST [963] LOG: database system was shut down at 2020-12-09 11:47:39 CST
2020-12-09 11:51:28.113 CST [963] LOG: recovering prepared transaction 16363 from shared memory
2020-12-09 11:51:28.132 CST [960] LOG: database system is ready to accept connections

如果你不希望恢復一個prepared transaction,可以簡單地刪除pg_twophase文件夾下的相應文件。

這很簡單,不是嗎?那么我們為什么不經常地使用它呢?畢竟,它提供了更高的提交操作成功的可能性。事情要是這么簡單就好了!

prepared transaction可能遇到哪些錯誤?

如果客戶端消失了,則prepared transaction可以未完成(既不提交也不回滾)。發生這種情況的原因多種多樣,包括客戶機崩潰,或者服務器崩潰導致客戶機連接被終止而無法重新連接。你實際上是依靠事務管理器來確保沒有孤立的prepared transaction。

除了崩潰之外,還有另一種原因可以使prepared transaction未完成。如果一個用于恢復的備份包含了事務的prepared階段,但是沒有包含關閉事務的階段,仍然會生成孤兒事務。

或者,DBA創建了一個prepared transaction,卻忘記了關閉它。

所以,如果一個prepared transaction沒有完成,又會有什么大不了的呢?

真正的問題

真正的問題是,孤兒prepared transaction繼續持有可能包含鎖的關鍵系統資源,或者使事務ID保持活動狀態,該事務ID可能會阻止vacuum清除只對該孤兒事務可見、對其它事務不可見的死的元組。

回想一下我在上面創建的prepared 事務。當事務prepared,并且在提交該事務之前,如果另一個事務試圖更改該表,它將無法獲取所需的鎖并掛起,直到解決了prepared事務(提交或回滾)為止。 否則,alter命令會無限期掛起,最終,我必須發出CTRL + C來停止該命令。

postgres=# select * from pg_prepared_xacts;
 transaction |  gid  |   prepared   | owner | database
-------------+--------------+-------------------------------+----------+----------
  16363 | abce_insert2 | 2020-12-09 11:46:01.983483+08 | postgres | postgres
(1 row)
 
postgres=# alter table abce add column b int;
^CCancel request sent
ERROR: canceling statement due to user request
postgres=# select c.oid,c.relname,l.locktype,l.relation,l.mode
postgres-# from pg_class c
postgres-# inner join pg_locks l on c.oid=l.relation
postgres-# where c.relname='abce';
 oid | relname | locktype | relation |  mode  
--------+---------+----------+----------+------------------
 370883 | abce | relation | 370883 | RowExclusiveLock
(1 row)
 
postgres=#

對vacuum的阻塞可能會更嚴重,在極端情況下,會導致數據庫關閉,因為孤兒prepared事務會阻止事務id的wrap around。

發現和通知

雖然一般的預期是prepared事務在幾秒鐘內完成,但是情況并不總是這樣。一個prepared事務可能持續幾分鐘、幾小時甚至幾天。

為這些事務維護元數據本身可能是一項挑戰。但是,我建議設置一個術語來定義prepared事務可以存在的最大時間。例如,考慮以下的prepared事務:

postgres=# BEGIN;
BEGIN
postgres=# INSERT INTO abce VALUES(3);
INSERT 0 1
postgres=# PREPARE TRANSACTION 'abce_insert 1m';
PREPARE TRANSACTION

或者下面的事務:

postgres=# BEGIN;
BEGIN
postgres=# INSERT INTO abce VALUES(4);
INSERT 0 1
postgres=# PREPARE TRANSACTION 'abce_insert 1d';
PREPARE TRANSACTION

在這些事務名稱中,最后一部分定義事務的時間。任何超出時間的事務可以通過sql查詢輕易地找出來:

postgres=# select gid,prepared,regexp_replace(gid, '.* ', '') AS age
from pg_prepared_xacts
WHERE prepared + CAST(regexp_replace(gid, '.* ', '') AS INTERVAL)  NOW();
  gid  |   prepared   | age
----------------+-------------------------------+-----
 abce_insert 1m | 2020-12-09 13:39:01.383091+08 | 1m
(1 row)
 
postgres=#

這里就很清晰地顯示了一個不應該再有效的事務。因此,使用一個外部代理或者cron任務可以輕易找出這些事務,或者通知管理員、或者回滾事務。

在我看來,這是一種簡單而容易的方式,可以確保即使事務管理器失敗或DBA意外地留下了一個事務,也可以在你的環境中管理孤兒事務。

結論

Prepared transactions顯然是一個非常重要的功能,但是需要使用回退通知程序或清理程序仔細設置環境,以輕松確保這些事務不會不必要地占用關鍵資源,并且系統保持良好狀態。

PostgreSQL社區中仍在討論如何處理孤兒prepared事務。它是否成為postgresql核心的一部分尚待觀察。同時,我們需要使用外部工具來管理這些事務,或者設法解決這個問題。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

您可能感興趣的文章:
  • PostgreSQL 對IN,EXISTS,ANY/ALL,JOIN的sql優化方案
  • postgresql 13.1 insert into select并行查詢的實現
  • PostgreSQL 啟動失敗的解決方案
  • 解決postgresql無法遠程訪問的情況
  • 淺談Postgresql默認端口5432你所不知道的一點
  • postgresql修改完端口后直接psql連接數據庫報錯的解決
  • postgresql 實現啟動、狀態查看、關閉
  • postgresql連續歸檔及時間點恢復的操作

標簽:榆林 濮陽 杭州 寶雞 辛集 溫州 海西 昭通

巨人網絡通訊聲明:本文標題《淺談PostgreSQL中的孤兒文件用法(orphaned data files)》,本文關鍵詞  淺談,PostgreSQL,中的,孤兒,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《淺談PostgreSQL中的孤兒文件用法(orphaned data files)》相關的同類信息!
  • 本頁收集關于淺談PostgreSQL中的孤兒文件用法(orphaned data files)的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    亚洲国产中文字幕在线视频综合| 五月综合激情网| 亚洲日本在线天堂| 顶级嫩模精品视频在线看| 精品国产露脸精彩对白| 精品一区免费av| 精品国内二区三区| 国产在线视频一区二区| 精品国产一二三| 蜜桃视频在线观看一区| 精品国产亚洲一区二区三区在线观看| 亚洲国产视频一区| caoporn国产精品| 亚洲综合免费观看高清在线观看| 欧美日韩国产综合一区二区| 久久成人免费电影| 自拍偷拍欧美激情| 911精品国产一区二区在线| 五月婷婷激情综合| 久久精品视频一区二区三区| 91原创在线视频| 天天亚洲美女在线视频| 在线不卡中文字幕播放| 国产精品一区二区三区网站| 国产女同性恋一区二区| 欧美日韩国产电影| 成人深夜在线观看| 亚洲国产精品久久久久秋霞影院| 日韩一区二区三区视频在线观看| 国产呦精品一区二区三区网站| 中文字幕不卡在线| 欧美精品乱码久久久久久按摩| 国产成人综合自拍| 一区二区三区加勒比av| 国产亚洲欧美一区在线观看| 色综合色综合色综合| 精品在线观看视频| 一区二区中文视频| 精品福利一二区| 欧美日韩精品一区二区三区四区 | 色婷婷av一区二区三区之一色屋| 日本免费在线视频不卡一不卡二| 国产精品久久精品日日| 精品国产在天天线2019| 欧美日本一道本| 欧美精品一区二区三区蜜桃| 欧洲一区二区三区免费视频| 国产精品1区2区3区在线观看| 亚洲成a人在线观看| 国产视频亚洲色图| 欧美一级片在线| 欧美日韩精品综合在线| 成人av网址在线观看| 国产成人免费在线观看| 狠狠色狠狠色综合日日91app| 日韩高清在线不卡| 亚洲综合久久久| 国产精品久久一卡二卡| 国产精品久久一卡二卡| 欧美精品一区在线观看| 欧美一区二区三区啪啪| 99精品久久只有精品| 国产91精品精华液一区二区三区| 亚洲精品成人少妇| 午夜久久福利影院| 亚洲人亚洲人成电影网站色| 亚洲日本一区二区| 亚洲国产精品一区二区尤物区| 91首页免费视频| 国产电影精品久久禁18| 天天影视涩香欲综合网 | 欧美v国产在线一区二区三区| 色噜噜狠狠色综合中国| 91麻豆高清视频| 欧美日韩精品一区二区在线播放| 欧美精品一级二级三级| 日韩一区二区三区高清免费看看| 日韩免费看的电影| 欧美激情在线一区二区三区| 亚洲丝袜另类动漫二区| 亚洲国产综合人成综合网站| 日本人妖一区二区| 国产盗摄女厕一区二区三区| 国产精品乱子久久久久| 日韩美女视频一区二区| 综合网在线视频| 亚洲成人免费影院| 久久不见久久见免费视频1| 久草中文综合在线| 国产99久久久国产精品潘金网站| 国产精品夜夜嗨| 在线成人免费视频| 亚洲精品一线二线三线| 亚洲天堂福利av| 亚洲国产一区二区视频| 国产精品1区二区.| 欧美日本一区二区三区四区| 欧美xxxx在线观看| 欧美精品一区二区在线播放| 久久综合一区二区| 中文字幕一区二区三区四区| 亚洲成人精品一区| 日韩**一区毛片| 91在线视频免费观看| 日韩一卡二卡三卡国产欧美| 久久久久久久久久久久电影| 国产视频视频一区| 青青草国产成人99久久| 东方aⅴ免费观看久久av| 欧美午夜在线一二页| 日韩免费成人网| 综合av第一页| 免费观看一级欧美片| 成a人片亚洲日本久久| 欧美日韩视频一区二区| 精品福利二区三区| 午夜国产不卡在线观看视频| 91在线观看高清| 国产精品久久久久久久久快鸭| 亚洲视频在线观看三级| 色婷婷av一区二区三区软件 | 久久精品网站免费观看| 日本人妖一区二区| 欧美群妇大交群中文字幕| 亚洲激情在线激情| 国产99久久久国产精品潘金网站| 欧美视频在线一区| 亚洲欧美一区二区久久| voyeur盗摄精品| 国产精品污www在线观看| 国产超碰在线一区| 国产日本欧洲亚洲| 粉嫩久久99精品久久久久久夜| 欧美va在线播放| 欧美aⅴ一区二区三区视频| 欧美在线一区二区三区| 一区二区三区在线观看网站| 99久久国产综合精品色伊| 国产精品天天看| 97精品国产露脸对白| 亚洲国产高清aⅴ视频| 国产成人自拍高清视频在线免费播放| 6080yy午夜一二三区久久| 亚洲一卡二卡三卡四卡五卡| 99久久精品免费精品国产| 中文字幕亚洲不卡| 国产凹凸在线观看一区二区| 国产精品久久久久影院亚瑟| 在线欧美日韩国产| 中文字幕一区二区三| 91浏览器打开| 五月婷婷色综合| 欧美成人福利视频| 久久精品99国产国产精| 久久综合五月天婷婷伊人| 国产精品77777| 亚洲美女在线国产| 51精品秘密在线观看| 九色综合国产一区二区三区| 国产亚洲精品久| 日本电影欧美片| 日本欧美大码aⅴ在线播放| 久久欧美一区二区| 成人一级黄色片| 午夜精品久久久久久久久久| 777xxx欧美| 精品亚洲aⅴ乱码一区二区三区| 日韩一卡二卡三卡| www.亚洲色图| 亚洲综合成人网| 精品国产一二三| 欧美午夜片在线观看| 午夜电影一区二区三区| 国产日韩欧美精品一区| 色偷偷一区二区三区| 狠狠网亚洲精品| 亚洲伦在线观看| 日韩精品中午字幕| 大陆成人av片| 久久99久久99小草精品免视看| 国产精品久久毛片a| www.亚洲在线| 在线免费不卡视频| 欧美在线一区二区三区| va亚洲va日韩不卡在线观看| 一区二区中文字幕在线| 欧美一三区三区四区免费在线看| 国产精品主播直播| 同产精品九九九| 亚洲视频精选在线| 久久亚洲一级片| 91精品一区二区三区久久久久久 | 亚洲成a人v欧美综合天堂下载| 精品国产一区二区三区不卡| 91国偷自产一区二区开放时间 | 日本一区二区免费在线| 91麻豆精品国产91| 在线看一区二区| 91亚洲精品久久久蜜桃网站| 国产老女人精品毛片久久|