postgres pg_receivewal代码分析
src\bin\pg_basebackup\pg_receivewal.c
main 468
初始化,参数解析,获取连接681,检查wal size 714
StreamLog(); src\bin\pg_basebackup\pg_receivewal.c 760
stream分配内存,获得数据库连接,检查版本,检查系统
FindStreamingStart(&stream.timeline); 406---》200 //根据目的文件夹中最大id的文件
,找最后的xlog segment,决定本次的起点。
获取目的目录src\port\dirent.c
得到文件
看是否是partical,是否压缩
XLogSegmentOffset(stream.startpos, WalSegSz); //找到在segment开始的地方复制下一个
设置stream
ReceiveXlogStream(conn, &stream); //从特定的position开始复制log stream
src\bin\pg_basebackup\receivelog.c 437
while(1){
if(!existsTimeLineHistoryFile){ //查看本地是否存在wal,如果是从上次结束的地方在开始
res = PQexec(conn, "TIMELINE_HISTORY %u"); //538
//参考http://www.postgres.cn/docs/14/protocol-replication.html
}
res = PQexec(conn, START_REPLICATION %s%X/%X TIMELINE %u");
//执行语句,指示服务器开始启动流WAL,从 WAL 位置XXX/XXX开始。如果TIMELINE选项被指定,流传送会在时间线tli上开始,否则会选择服务器的当前时间线。完成这个操作后,后面只需要从本地buffer中读取和处理。参考http://www.postgres.cn/docs/14/protocol-replication.html
PQexecStart(conn)
PQsendQuery(conn, query)
PQsendQueryInternal(conn, query, true);
pqPutMsgStart('Q', conn)
pqPuts(query, conn)
pqPutMsgBytes(s, strlen(s) + 1, conn)
memcpy(conn->outBuffer + conn->outMsgEnd, buf, len);//这里放到了socket发送buffer中就可以自动完成发送的任务。
pqPutMsgEnd(conn)
PQexecFinish(conn)
HandleCopyStream(conn, stream, &stoppos); //处理query返回的stream包
CopyStreamReceive()
rawlen = PQgetCopyData //从socket buffer中copy到用户态
pqGetCopyData3
getCopyDataMessage
pqGetc //获取一个char,表示类型
pqGetInt //int 表示这个包的size length
malloc //如果rawlen!=0, 根据获得的长度,分配内存,并从socketbuf中拷贝到用户态
memcpy
if(rawlen == 0)
CopyStreamPoll
select //使用linux select等待数据到达,直到超时
pqReadData //select拿到通知,数据已经到达
pqReadData
pqsecure_read
pqsecure_raw_read
recv //linux socket api 从socket中收数据
while(1) {
r = CopyStreamReceive(conn, sleeptime, stream->stop_socket, ©buf);
rawlen = PQgetCopyData(conn, ©buf, 1);
return pqGetCopyData3(conn, buffer, async);
for;;{
msgLength = getCopyDataMessage(conn); //获取一行的message数据,message是stream的控制信息,后面的keep live,或者是wal data等信息。
pqGetc(&id, conn) //从socket连接中获取
pqGetInt //int 表示这个包的size length
malloc //根据获得的长度,分配内存,并从socketbuf中拷贝到用户态
memcpy
}
while (r != 0)//一次query持续在这个循环中接收和处理服务器发送来的package,除非超时退出此循环
{
根据获取到的服务器massage,不同操作
if (copybuf[0] == 'k')
{
ProcessKeepaliveMsg(conn, stream, copybuf, r, blockpos,
&last_status)
}
else if (copybuf[0] == 'w')
{
ProcessXLogDataMsg(conn, stream, copybuf, r, &blockpos)
write(walfile, copybuf + hdr_len + bytes_written,bytes_to_write) //这里完成写本地文件,完成备份。
}
CopyStreamReceive //同上
}
}
}
作者:skpupil
出处:https://www.cnblogs.com/skpupil/p/16414475.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
分类:
PostgreSQL
Buy me a cup of coffee ☕.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构