PostgreSQL如何删除不使用的xlog文件

作者&投稿:微馨 (若有异议请与网页底部的电邮联系)
~

一、问题
经常会在复制的时候遇到这样的问题,需要复制的xlog文件找不到了。那么xlog文件什么时候删除?又会删除多少保留多少个xlog文件?都有哪些xlog文件需要保留?本文将从原理上对这些问题进行解读。

二、原理
每次checkpoint后都会根据需要删除或者回收不再需要的xlog文件。
1、首先估算两次checkpoint之间产生的xlog量,根据这个量会计算出未来最大的日志文件号从而回收不再需要的文件将其重命名为未来即将使用的日志文件号:
1.1 UpdateCheckPointDistanceEstimate估算checkpoint之前产生的日志量:
?? ?if (CheckPointDistanceEstimate < nbytes)//上次估算量比这次估算的小,则更新为这次的估算量
?? ??? ?CheckPointDistanceEstimate = nbytes;
?? ?else//否则,适当增加
?? ??? ?CheckPointDistanceEstimate =(0.90CheckPointDistanceEstimate + 0.10(double) nbytes);
2、计算上一次checkpoint时,所在的文件段号_logSegNo:
?? ?XLByteToSeg(PriorRedoPtr, _logSegNo);
3、计算需要保留的文件段号:从该段号_logSegNo开始的文件都不能被删除,之前的需要删除或回收:根据备机请求以及wal_keep_segments计算KeepLogSeg(recptr, &_logSegNo);


4、遍历pg_wal目录下的所有xlog文件,进行删除:RemoveOldXlogFiles
4.1 跳过时间线进行比较,如果pg_wal目录下的文件比_logSegNo小则被删除或回收。那么什么条件下次被回收?
--RemoveXlogFile
4.2 计算回收文件重命名的未来最大文件段号recycleSegNo:
?? ?1)如果本次是第一次checkpoint,则未来最大段号recycleSegNo=当前段文件号+10
?? ?2)否则调用函数XLOGfileslop计算:
?? ??? ?2.1 估算下一次checkpoint结束时日志位置:
?? ??? ??? ?distance=(2.0+checkpoint_completion_target)CheckPointDistanceEstimate
?? ??? ??? ?distance=1.1
?? ??? ??? ?recycleSegNo = (XLogSegNo) ceil(((double) PriorRedoPtr + distance) / XLOG_SEG_SIZE);
?? ??? ?2.2 minSegNo = PriorRedoPtr / XLOG_SEG_SIZE + ConvertToXSegs(min_wal_size_mb) - 1;
?? ??? ??? ?maxSegNo = PriorRedoPtr / XLOG_SEG_SIZE + ConvertToXSegs(max_wal_size_mb) - 1;
?? ??? ?2.3 if (recycleSegNo < minSegNo)
?? ??? ??? ??? ?recycleSegNo = minSegNo;
?? ??? ??? ?if (recycleSegNo > maxSegNo)
?? ??? ??? ??? ?recycleSegNo = maxSegNo;
4.3 如果当前段文件号endlogSegNo < recycleSegNo,则调用InstallXLogFileSegment进行回收:
?? ?1)在endlogSegNo和recycleSegNo之间找一个free slot num,即没有该段文件号的xlog文件
?? ?2)将需要删除的文件名命名为该free slot号的文件名
?? ?3)如果没有找到free slot则直接删除该文件
--RemoveXlogFile

三、代码流程
1、checkpoint顶层函数CreateCheckPoint:

CreateCheckPoint:
XLogCtlInsert *Insert = &XLogCtl->Insert;//标识插入的位置
curInsert = XLogBytePosToRecPtr(Insert->CurrBytePos);//添加页头大小后的位置
//(((curInsert) % XLOG_BLCKSZ == 0) ? 0 : (XLOG_BLCKSZ - (curInsert) % XLOG_BLCKSZ))
freespace = INSERT_FREESPACE(curInsert);//curInsert所在页是否有空闲空间
if (freespace == 0){
if (curInsert % XLogSegSize == 0)//正好一个xlog段文件用完,即将使用下一个段文件,则跳过36字节
curInsert += SizeOfXLogLongPHD;//36字节
else//xlog段文件中正好一页用完,即将使用下一页,则跳过20字节
curInsert += SizeOfXLogShortPHD;//20字节
}
checkPoint.redo = curInsert;//xlog文件上,实际的即将插入位置
RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
...
//插入checkpoint记录后末尾位置,即下一个xlog开始的位置
recptr = XLogInsert(RM_XLOG_ID,shutdown ? XLOG_CHECKPOINT_SHUTDOWN :XLOG_CHECKPOINT_ONLINE);
...
PriorRedoPtr = ControlFile->checkPointCopy.redo;//上一次checkpoint的起始位置
...
if (PriorRedoPtr != InvalidXLogRecPtr){//上一次checkpoint开始到这一次checkpoint开始,产生的XLOG大小为入参
/*
CheckPointDistanceEstimate:
1、CheckPointDistanceEstimate<RedoRecPtr - PriorRedoPtr时:RedoRecPtr - PriorRedoPtr
2、CheckPointDistanceEstimate>=RedoRecPtr - PriorRedoPtr时:0.9*CheckPointDistanceEstimate+0.1*(RedoRecPtr - PriorRedoPtr)
*/
UpdateCheckPointDistanceEstimate(RedoRecPtr - PriorRedoPtr);
//_logSegNo = (PriorRedoPtr) / XLogSegSize
XLByteToSeg(PriorRedoPtr, _logSegNo);
KeepLogSeg(recptr, &_logSegNo);
_logSegNo--;
RemoveOldXlogFiles(_logSegNo, PriorRedoPtr, recptr);
2、两个宏定义

#define UsableBytesInPage (XLOG_BLCKSZ - SizeOfXLogShortPHD)//注意:不是文件第一页
#define UsableBytesInSegment ((XLOG_SEG_SIZE / XLOG_BLCKSZ) * UsableBytesInPage - (SizeOfXLogLongPHD - SizeOfXLogShortPHD))
3、函数XLogBytePosToRecPtr

static XLogRecPtr
XLogBytePosToRecPtr(uint64 bytepos)
{
//bytepos:不包括xlog页的页头等额外字节占用的大小
fullsegs = bytepos / UsableBytesInSegment;
bytesleft = bytepos % UsableBytesInSegment;
/*
1、如果bytesleft < XLOG_BLCKSZ-32,则表示定位到第一页上,则文件偏移值跳过第一页页头大小
2、如果bytesleft >= XLOG_BLCKSZ-32,则表示定位不是第一页
*/
if (bytesleft < XLOG_BLCKSZ - SizeOfXLogLongPHD){
/* fits on first page of segment */
seg_offset = bytesleft + SizeOfXLogLongPHD;
}else{
/* account for the first page on segment with long header */
seg_offset = XLOG_BLCKSZ;//先跳过第一页
bytesleft -= XLOG_BLCKSZ - SizeOfXLogLongPHD;//去掉第一页存放XLOG的大小
fullpages = bytesleft / UsableBytesInPage;//剩下的需要几个页
bytesleft = bytesleft % UsableBytesInPage;//剩下的偏移
// 文件偏移=第一页大小+剩下的几个页大小+剩下的偏移+最后一页的页头
seg_offset += fullpages * XLOG_BLCKSZ + bytesleft + SizeOfXLogShortPHD;
}
//result=(fullsegs) * XLOG_SEG_SIZE + seg_offset
XLogSegNoOffsetToRecPtr(fullsegs, seg_offset, result);
return result;
}
4、函数KeepLogSeg

static void
KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
{
//segno为当前xlog即将插入位置在第几个文件上
XLByteToSeg(recptr, segno);
//XLogCtl->replicationSlotMinLSN;备机上请求预留的最小值?
keep = XLogGetReplicationSlotMinimumLSN();
/* compute limit for wal_keep_segments first */
if (wal_keep_segments > 0){
/*
首先计算wal_keep_segments得到的限制:
1、比如wal_keep_segments值是10,若当前insert的位置的文件号segno为5,那么向前推进到1
2、否则向前推进wal_keep_segments后的segno前的可删除
*/
if (segno <= wal_keep_segments)
segno = 1;
else
segno = segno - wal_keep_segments;
}
/* then check whether slots limit removal further */
//计算slots限制,如果其算出的值小于wal_keep_segments计算出的值,则需要使用slotSegNo,slots还有用,不能删除
if (max_replication_slots > 0 && keep != InvalidXLogRecPtr){
XLByteToSeg(keep, slotSegNo);
if (slotSegNo <= 0)
segno = 1;
else if (slotSegNo < segno)
segno = slotSegNo;
}
/* don‘t delete WAL segments newer than the calculated segment */
if (segno < *logSegNo)
*logSegNo = segno;
//note:
//如果计算出的segno比上次checkpoint时的文件号logSegNo还有小,则取这次计算的segno
//如果计算出的segno比上次checkpoint时的文件号logSegNo大,则取上次checkpoint时的文件号。
//因为恢复时如果是主机,读取最新checkpoint记录失败后,会读取上一次checkpoint记录,如果上次checkpoint的文件被删除,这里就读取不到记录了
}
5、函数RemoveOldXlogFiles
static void
RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
{
//首先获取xlog目录
xldir = AllocateDir(XLOGDIR);
if (xldir == NULL)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open write-ahead log directory \"%s\": %m",
XLOGDIR)));

/*
构建一个log文件名,用于判断,该文件之前的xlog可以删除。用不到时间线,所以可以使用0
*/
XLogFileName(lastoff, 0, segno);
while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL){
/* 忽略非xlog文件 */
if (!IsXLogFileName(xlde->d_name) &&
!IsPartialXLogFileName(xlde->d_name))
continue;
/*
1、跳过时间线进行比较
*/
if (strcmp(xlde->d_name + 8, lastoff + 8) <= 0){
if (XLogArchiveCheckDone(xlde->d_name)){//如果没有开启归档:总是TRUE;否则,归档完成后才为TRUE
/* Update the last removed location in shared memory first */
//XLogCtl->lastRemovedSegNo = segno;
UpdateLastRemovedPtr(xlde->d_name);
RemoveXlogFile(xlde->d_name, PriorRedoPtr, endptr);
}
}
}
}

6、函数RemoveXlogFile
RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
{

XLByteToSeg(endptr, endlogSegNo);
if (PriorRedoPtr == InvalidXLogRecPtr)
recycleSegNo = endlogSegNo + 10;
else
recycleSegNo = XLOGfileslop(PriorRedoPtr);
snprintf(path, MAXPGPATH, XLOGDIR "/%s", segname);
if (endlogSegNo <= recycleSegNo &&
lstat(path, &statbuf) == 0 && S_ISREG(statbuf.st_mode) &&
InstallXLogFileSegment(&endlogSegNo, path,
true, recycleSegNo, true))
{
endlogSegNo++;
}else{
rc = durable_unlink(path, LOG);
}
}

7、函数InstallXLogFileSegment
static bool
InstallXLogFileSegment(XLogSegNo segno, char tmppath,
bool find_free, XLogSegNo max_segno,
bool use_lock)
{
XLogFilePath(path, ThisTimeLineID, segno);
/

We want to be sure that only one process does this at a time.
*/
if (use_lock)
LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);

if (!find_free)
{
/ Force installation: get rid of any pre-existing segment file /
durable_unlink(path, DEBUG1);//删除文件并持久化到磁盘
}else{
/ Find a free slot to put it in /
while (stat(path, &stat_buf) == 0){//获取文件信息并保存到stat_buf中,成功返回0
//在segno和max_segno之间找一个空闲的段号,即目录中没有这个段号的xlog文件
if ((segno) >= max_segno){
/ Failed to find a free slot within specified range /
if (use_lock)
LWLockRelease(ControlFileLock);
return false;
}
(segno)++;
XLogFilePath(path, ThisTimeLineID, segno);
}
}
if (durable_link_or_rename(tmppath, path, LOG) != 0){//将tmppath重命名为path并持久化
if (use_lock)
LWLockRelease(ControlFileLock);
/ durable_link_or_rename already emitted log message */
return false;
}
if (use_lock)
LWLockRelease(ControlFileLock);
return true;
}

PostgreSQL如何删除不使用的xlog文件
标签:newocarablwithwhethersegmenttpsniminstall




如何提高postgresql查询性能
PostgreSQL为每个查询都生成一个查询规划,因为选择正确的查询路径对性能的影响是极为关键的。PostgreSQL本身已经包含了一个规划器用于寻找最优规划,我们可以通过使用EXPLAIN命令来查看规划器为每个查询生成的查询规划。 PostgreSQL中生成的查询规划是由1到n个规划节点构成的规划树,其中最底层的节点为表扫描节点,用于从数据表...

postgresql启动失败
1、看看服务里的 Postgres 服务的用户名、密码,必须用 postres 用户启动的。2、鉴于重启后就启动不了,是不是服务设置手动,或者是安装了影子系统 3、会不会是安装的时候,上一次的安装没有卸载干净?4、手动启动服务试试看,看看系统日志有没有相应内容分。5、到 c:\\program files下的安装目录(...

PostgreSQL与MySQL相比,优势何在?
PostgreSQL类似于Oracle的多进程框架,可以支持高并发的应用场景。 如果把OracleDBA转到PostgreSQL数据库上是比较容易的,毕竟PostgreSQL数据库与Oracle数据库很相似。 PostgreSQL几乎支持所有的SQL标准,支持类型相当丰富。PostgreSQL数据库的源代码要比MySQL数据库的源代码更容易读懂,如果团队的C语言能力比较强的话,就可以在Postg...

如何运行远程客户端连接postgresql数据库
安装PostgreSQL数据库之后,默认是只接受本地访问连接。如果想在其他主机上访问PostgreSQL数据库服务器,就需要进行相 应的配置。配置远程连接PostgreSQL数据库的步骤很简单,只需要修改data目录下的pg_hba.conf和postgresql.conf, 其中pg_hba.conf是用来配置对数据库的访问权限,postgresql.conf文件用来配置...

三分钟!彻底搞懂PostgreSQL 和 MySQL 区别之分
PostgreSQL 和 MySQL 是将数据组织成表的关系数据库。这些表可以根据每个表共有的数据链接或关联。关系数据库使您的企业能够更好地了解可用数据之间的关系,并帮助获得新的见解以做出更好的决策或发现新的机会。PostgreSQL 和 MySQL 都依赖于 SQL(结构化查询语言),这是与管理系统交互的标准语言。SQL ...

安装postgre sql时跳出langid怎么解决
安装postgre sql时跳出langid解决方法:一、安装 首先,安装PostgreSQL客户端。sudo apt-get install postgresql-client 然后,安装PostgreSQL服务器。sudo apt-get install postgresql 正常情况下,安装完成后,PostgreSQL服务器会自动在本机的5432端口开启。如果还想安装图形管理界面,可以运行下面命令,但是本文...

postgresql 和postgis区别是什么?
本文中 ‘PostgreSQL’ 指代基本的关系数据库功能,而‘PostGIS’ 指代扩展的空间操作特性。 客户端-服务器构架 PostgreSQL 同众多数据库产品一样,采用客户端-服务器构架。客户端向服务器发出请求并得到响应。这种机制同浏览器从网络服务器获取网页类似。在 PostgreSQL 中,请求以 SQL 语言发出,而响应多为从数据库提取...

怎样用postgresql建表,建数据库
PostgreSQL的CREATE TABLE语句是用来在任何指定的的数据库中创建一个新表。 yiibai.com 语法 CREATE TABLE语句的基本语法如下:CREATE TABLE table_name(column1 datatype,column2 datatype,column3 datatype,...columnN datatype,PRIMARY KEY( one or more columns ));CREATE TABLE是告诉数据库系统关键...

postgreSQL数据库有什么用啊?
优点事实上, PostgreSQL 的特性覆盖了 SQL-2\/SQL-92 和 SQL-3\/SQL-99,首先,它包括了可以说是目前世界上最丰富的数据类型的支持,其中有些数据类型可以说连商业数据库都不具备, 比如 IP 类型和几何类型等;其次,PostgreSQL 是全功能的自由软件数据库,很长时间以来,PostgreSQL 是唯一支持事务、子...

如何在CentOS 7\/6.5\/6.4 下安装PostgreSQL 9.3 与 phpPgAdmin
PostgreSQL是一个强大开源的对象关系类型数据库系统,它能运行于几乎所有主要的操作系统,包括Linux、Unix(AIX、BSD、HP-UX、SGI IRIX、Mac OS、Solaris、Tru64)、Windows OS。在这篇教程里,我们将学习如何在CentOS7\/6.5\/6.4 server 中建立PostgreSQL。1.安装PostgreSQL 首先根据你的服务器架构添加...

肥东县18622445339: PostgreSQL如何卸载? -
寸博派丽: apt-get --purge remove postgresql

肥东县18622445339: 请教如何删除PostgreSQL 9.2 -
寸博派丽: 这里针对的是 9.3 版本.如是其他版下面的仅供参考. 1、如果是postgresql.app的形式,这个简单,跟其他app一样,删除app即可. 2、如果是使用installer图形界面方式安装的.则需要打开终端命令行. 3、执行 open /Library/PostgreSQL/9.2/...

肥东县18622445339: 如何关掉postgresql数据库 -
寸博派丽: 直接在命令行输入:quit或者是exist即可完成退出. 备注:其实最简单的方法就是关闭登录窗口,或者切换用户的形式完成退出当前用户的数据库操作.

肥东县18622445339: postgresql 8.4 数据库如何在windows下删除?急需电脑高手解答! -
寸博派丽: 控制面板---添加/删除程序("程序和功能")---找到PostgreSQL 8.4,卸载即可.

肥东县18622445339: 源码编译安装postgresql后怎么卸载 -
寸博派丽: 建议你装个腾讯电脑管家.管家的管理功能挺完善的.而且各项管理能力也都比较出众.如需卸载,可通过管家软件管理平台完成相关管理:打开腾讯电脑管家~~~~工具箱~~~~软件卸载~~~~强力删除 同时,垃圾清理还可以清除卸载残留文件及注册表信息:打开腾讯电脑管家~~~~工具箱~~~~清理垃圾/注册表垃圾

肥东县18622445339: 如何将postgres从linux卸载重装 -
寸博派丽: 有软件包依赖postgresql,如果删了,这些软件也无法正常使用: postfix、postgresql-libs 如果确认不需要,可以先卸载这两个包 强制卸载postgresql-libs也行

肥东县18622445339: 如何卸载postgresql -
寸博派丽: 开始-运行-appwiz.cpl 找到然后卸载就好了

肥东县18622445339: 怎么在win8中删除postgresql -
寸博派丽: 数据行可以用 DELETE 命令从表中删除. 假设你对Hayward的天气不再感兴趣,那么你可以用下面的方法把那些行从表中删除:DELETE FROM weather WHERE city = 'Hayward'; 所有属于Hayward的天气记录都将被删除.SELECT * FROM ...

肥东县18622445339: 怎么使用linux命令 删除postgresql表 -
寸博派丽: 两种办法 [1]在命令行用dropdb命令删除 dropdb -U postgres demodb,就可以实现数据库的删除 [2]在psql命令行下删除 psql#DROP DATABASE demodb 执行就可以删除.

肥东县18622445339: postgresql如何删除操作历史记?postgresql如何
寸博派丽: 1. 清除“开始/文档”中曾经打开的文件列表 这是一个最明显的操作痕迹,明白的... 另外,使用“开始/查找/文件或文件夹”命令,查找*. tmp等各种临时文件,然后删除...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网