pg源码阅读二

来源:互联网 发布:php网站源码与asp.net 编辑:程序博客网 时间:2024/05/11 21:38

postmaster中使用AuxiliaryProcessMain来启动bgwriter walwriter等,在该类中去分别启动不同的辅助进程
switch (auxType)
{
case CheckerProcess:
bootstrap_signals();
CheckerModeMain();
proc_exit(1); /* should never return */

    case BootstrapProcess:        bootstrap_signals();        BootStrapXLOG();        StartupXLOG();        BootstrapModeMain();        proc_exit(1);       /* should never return */    case StartupProcess:        /* don't set signals, startup process has its own agenda */        StartupProcessMain();        proc_exit(1);       /* should never return */    case BgWriterProcess:        /* don't set signals, bgwriter has its own agenda */        BackgroundWriterMain();        proc_exit(1);       /* should never return */    case WalWriterProcess:        /* don't set signals, walwriter has its own agenda */        InitXLOGAccess();        WalWriterMain();        proc_exit(1);       /* should never return */    default:        elog(PANIC, "unrecognized process type: %d", auxType);        proc_exit(1);}在进入循环后,会使用AbsorbFsyncRequests来处理fsync请求,并传送给本地smgr(神码东西??),该函数中使用LWLockAcquire(BgWriterCommLock, LW_EXCLUSIVE);来获取lw拍他锁,/*

* LWLockAcquire - acquire a lightweight lock in the specified mode
*
* If the lock is not available, sleep until it is.
*
* Side effect: cancel/die interrupts are held off until lock release.
*/
void
LWLockAcquire(LWLockId lockid, LWLockMode mode)
同时获得lw锁是有限制的
if (num_held_lwlocks >= MAX_SIMUL_LWLOCKS)
elog(ERROR, “too many LWLocks taken”);
最大值是100
lw锁的类型有下面几种
typedef enum LWLockId
{
BufFreelistLock,
ShmemIndexLock,
OidGenLock,
XidGenLock,
ProcArrayLock,
SInvalReadLock,
SInvalWriteLock,
WALInsertLock,
WALWriteLock,
ControlFileLock,
CheckpointLock,
CLogControlLock,
SubtransControlLock,
MultiXactGenLock,
MultiXactOffsetControlLock,
MultiXactMemberControlLock,
RelCacheInitLock,
BgWriterCommLock,
TwoPhaseStateLock,
TablespaceCreateLock,
BtreeVacuumLock,
AddinShmemInitLock,
AutovacuumLock,
AutovacuumScheduleLock,
SyncScanLock,
/* Individual lock IDs end here */
FirstBufMappingLock,
FirstLockMgrLock = FirstBufMappingLock + NUM_BUFFER_PARTITIONS,

/* must be last except for MaxDynamicLWLock: */NumFixedLWLocks = FirstLockMgrLock + NUM_LOCK_PARTITIONS,MaxDynamicLWLock = 1000000000

} LWLockId;

typedef enum LWLockMode
{
LW_EXCLUSIVE,
LW_SHARED
} LWLockMode;

这种lw轻量级锁是获取mutex
/* Acquire mutex. Time spent holding mutex should be short! */
SpinLockAcquire(&lock->mutex);
获得锁后,拷贝了请求数组来减少持有锁的时间
typedef struct
{
RelFileNode rnode;
ForkNumber forknum;
BlockNumber segno; /* see md.c for special values */
/* might add a real request-type field later; not needed yet */
} BgWriterRequest;
n = BgWriterShmem->num_requests;
if (n > 0)
{
requests = (BgWriterRequest ) palloc(n sizeof(BgWriterRequest));
memcpy(requests, BgWriterShmem->requests, n * sizeof(BgWriterRequest));
}
BgWriterShmem->num_requests = 0;
然后就写文件了
for (request = requests; n > 0; request++, n–)
RememberFsyncRequest(request->rnode, request->forknum, request->segno);

循环在处理完写磁盘的请求后,会检查与最后一次检查点的时间间隔,如果超过了阀值,就做个时间检查点
elapsed_secs = now - last_checkpoint_time;
if (elapsed_secs >= CheckPointTimeout)
{
if (!do_checkpoint)
BgWriterStats.m_timed_checkpoints++;
do_checkpoint = true;
flags |= CHECKPOINT_CAUSE_TIME;
}
在做检查点中,会判断下是否需要做重启点(这个是神码东西??)
do_restartpoint = RecoveryInProgress();
然后根据flag判断是神码类型的检查点,started_counter计数器增加
然后做个检查点,释放smgr
*/
if (!do_restartpoint)
{
CreateCheckPoint(flags);
ckpt_performed = true;
}
else
ckpt_performed = CreateRestartPoint(flags);
检查点类型有下面几种
* flags is a bitwise OR of the following:
* CHECKPOINT_IS_SHUTDOWN: checkpoint is for database shutdown.
* CHECKPOINT_END_OF_RECOVERY: checkpoint is for end of WAL recovery.
* CHECKPOINT_IMMEDIATE: finish the checkpoint ASAP,
* ignoring checkpoint_completion_target parameter.
* CHECKPOINT_FORCE: force a checkpoint even if no XLOG activity has occured
* since the last one (implied by CHECKPOINT_IS_SHUTDOWN or
* CHECKPOINT_END_OF_RECOVERY).
*
* Note: flags contains other bits, of interest here only for logging purposes.
* In particular note that this routine is synchronous and does not pay
* attention to CHECKPOINT_WAIT.
检查点是写脏数据,这个后面在看。
如果不需要检查点,就BgBufferSync();通过做一次脏缓存的写
/*
* BgBufferSync – Write out some dirty buffers in the pool.
*
* This is called periodically by the background writer process.
*
bgwriter负责检查点,会在一段时间后启动检查点,也可以处理请求的检查点,正常的停止是接受SIGUSR2的信号,会执行一个关闭的检查点然后推出。
与bgwriter相关的参数,
bgwriter_delay: Specifies the delay between activity rounds for the background writer. Default is 200ms.

bgwriter_lru_maxpages: In each round, no more than this many buffers will be written by the background writer. Setting this to zero disables background writing (except for checkpoint activity). The default value is 100 buffers.

bgwriter_lru_multiplier: The number of dirty buffers written in each round is based on the number of new buffers that have been needed by server processes during recent rounds. The default is 2.0.
在程序中看下是怎么使用的

smgr是存储介质管理器,缓冲区与存储的交互就是通过smgr来进行的。smgr管理不同的存储对上提供统一的接口,磁盘管理器与物理文件之间还存在一层vfd(虚拟文件描述符),为了防止进程打开的文件数量超过操作系统的限制,vdf通过有限的文件提供无限的vdf请求。
fsm:为了快速的找到可用的空闲块,pg提供了一个附属文件,就是空闲空间映射表,记录每个表文件块的空闲空间大小,
vm:为了查找哪些元组是被删除的,设置了一个附属文件,主要是提供快速查找能力。
hot,对于哪些没有更改索引属性的行的变更,减少索引空间。

0 0
原创粉丝点击