当前位置: 首页 > 科技观察

想学PostgreSQL,就得过DB架构

时间:2023-03-20 00:08:21 科技观察

在学习PostgreSQL的过程中,很容易陷入看似什么都懂,问起来却含糊其辞的境地。今天,我将经历这个烂摊子。Postgresql从daemon进程启动,daemon进程具有强大的功能,如执行恢复、初始化共享数据结构/内存空间、启动强制和可选进程等。PostgreSql启动后,开始接受客户访问。下图演示了客户如何申请连接,守护进程分配一个子进程为客户服务。当数以千计的用户要读取数据库中的数据,并希望以更高的速度读取时,就会涉及到PG中的内存系统。在PG的内存系统中,客户与后端进程进行交互,后端进程会与PG共享缓冲区,与其他数据库不同的是PG的内存不会与其他三个数据库相同,而且它需要的buffer设置不会特别大(相对于其他三个公司),他的设计也是用了LINUX系统的buffer系统,读取数据不会有问题,速度也会有保证。除了这两级缓存之外,我们还可以使用磁盘控制器缓存、磁盘驱动器缓存等。以上基本都是针对数据库的读操作。写操作中的一个问题是大量数据的改变和插入。数据是否会立即刷新?数据文件执行写操作。这可能只会导致确保预写日志(WAL)文件与WAL缓冲区保持同步。如何保证事务的持久化和事务的原子性?WAL日志的重要作用是保证系统高性能下的AD功能,使数据文件中的数据最终一致。通过buffercache和oid2name命令可以看到当前数据库的buffer中已经有哪些数据库在内存中。当然,如果你想关心user表的buffer读取的数据块的浮动情况,可以把上面的query保存在一个表中,补上时间,这样就可以画出burfer的周期表的用户表。(想想自己能干什么,很有意思)SELECTc.relname,count(*)ASbuffersFROMpg_classcJOINpg_buffercachebONb.relfilenode=c.relfilenodeINNERJOINpg_databasedON(b.reldatabase=d.oidANDd.datname=current_database())WHEREc.relnameNOTLIKE'pg%'GROUPBYc。relnameORDERBY2DES然后我们来进行内存和磁盘的交换,checkpoint,如果数据不能一直存在内存中,需要放到磁盘上,这就涉及到下一个checkpoint,checkpoint,checkpoint是一个强制过程,PG中的数据总是以数据块为单位进行写入和读取,无论该块数据是否占用8K,读取时也是以块为单位进行读取,用户在buffer、buffer和physicaldisk如果数据文件不一致,缓冲区中的数据是脏的。Checkpoint的作用是将确认的变化数据写入数据文件。所有相关的数据页和索引页都会被更新,并且这个页面会被标记为OK。这样就可以把这个checkpoint之前的HEAPPAGE和INDEXPAGE页面刷到磁盘上的数据文件中。所以我能理解的是,如果此时数据库没有任何其他手段,此时断电,CHECKPOINT之后的数据就会丢失(当然实际情况中不会),这就是redo,而redolog需要检查checkpoint的三个参数,checkpoint_segments、checkpoint_timeout、checkpoint_completion_target。(PG9X)三个参数中的前两个属于多少wal才够启动checkpoint。如果长时间没有checkpoint则根据第二个参数checkpint_timeout的时间进行Checkpoint。当然,这样做的后果是,如果某个阶段的数据量比较大,I/O会消耗很多。然后第三个参数,checkpoint_completion_target是启动函数,可以稍微缓和一下这种突发情况,延长写入时间,让I/O系统不那么忙。不过目前PG11中checkpoint相关的参数不再有checkpoint_segments,而是换成max_wal_size,要么超过设定的checkpoint时间,要么超过max-wal-size做checkpoint。我觉得这个设置比较合理。如果你用上面的方法,其实是用了一个函数,可以让PG的checkpoint乱序,甚至可能导致宕机(坏办法就算了)。最后,应该在wal日志中结束抚摸活动。当我们对数据进行更改时,并不会立即将更改写入数据文件,而是更改缓冲区中的块,将这些更改的记录写入WAL缓冲区,所以wal是系统运行效率的保证和数据安全产品之间的妥协。选择*frompg_walfile_name(pg_current_wal_lsn());如何知道自己当前操作的wal日志。(PG11)选择pg_xlogfile_name(pg_current_xlog_location());(PG9X)用过PG的都知道,PG是没有DOUBLEWRITE的功能的(DW是数据库的特性,不说了),是FULLPAGE支持的。毕竟FULLPAGE是用什么方法来避免DW,保证数据的完整性。当然这也消耗了系统的I/O性能,同时可以通过微调一些参数来缓解一些性能问题。在此之前,先说说为什么会出现这样的情况。如果数据页是8KB,那么硬件和系统可以一次把所有这些信息写入磁盘。答案当然是否定的,不是的,LINUX一次是4KB。连是4KB还是8KB都不知道,所以万一系统死机了,你写了8KB,别人写了4KB,然后就坏了,剩下的4KB就丢了怎么办?如果启动后物理页面损坏,谁给你?修复它,你修复它。因此,不同的数据库都有自己的特殊技能,我们必须弥补这一点。PG这里是整页。主要操作是PostgreSQL服务器在checkpoint后第一次修改页面时,会将每个磁盘页面的全部内容写入WAL。这样做的好处是,如果在下一个检查点之前的几个周期发生崩溃,我们就拥有了WAL中的所有数据页,通过它可以恢复数据。不好的是数据写入WAL日志,数据写入多了肯定会影响性能。这里,如果我们提高checkpoint频率,从逻辑上会抵消FULLpage的影响,而如果我们降低checkpoint频率,可能会人为地造成一个大的burstwrite,上面的参数被调整了,怎么办那个参数,我想你已经知道了。但结果是我不会关闭FULLPAGE,因为性能和数据安全应该是优先考虑的,不用说。以上内容由东方锐通高级讲师Austin提供。他拥有13年的专业DBA经验。曾任互联网金融公司高级DBA,500强医药公司高级DBA。精通Mysql、PostgreSQL、MongoDB、SQLServer。