暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL后端架构概述

作者:Cary Huang

简介:资深软件开发工程师,2012年获得University of British Columnbia(UBC)电气工程学士学位,有超过8年的C/C++开发经验,在如下领域有丰富的实践经验:PostgreSQL和非关系数据库Docker部署管理、软件工程生命周期、身份验证、密码学等。

1.简介

PostgreSQL后端是由称为Postmaster的主进程派生出来的进程的集合。每个派生出的进程在后端具有不同的角色和职责。本文介绍了当今我们所知的,支持PostgreSQL系统的核心后端进程的职责。下图显示了整个PostgreSQL后端体系架构:
Postmaster是第一个要启动的进程,它控制所有后端进程,并负责接受和关闭数据库连接。在启动时,postmaster派生了多个后端进程,这些后端进程用于处理不同的后端任务,这些我们将在这篇文章中介绍。当用户启动连接到PostgreSQL数据库时,客户端进程将向Postmaster主进程发送一条身份验证消息。postmaster主进程会根据配置的身份验证方法对用户进行身份验证,且仅当用户通过身份验证时,派生一个新会话来为该用户提供服务。

2. BgWriter(Background Writer)进程

BgWriter进程是将共享内存中的脏页写入磁盘的进程。它有两个功能:一个是周期性地从内存缓冲区中清除脏数据到磁盘,以减少在查询期间的阻塞;另一种情况是,PG需要在常规检查点期间将所有脏页写到磁盘。通过BgWriter提前写出一些脏页面,可以减少执行检查点(一种数据库恢复技术)时要执行的IO操作,从而使系统的IO负载趋于稳定。BgWriter是一个在PostgreSQL v8.0之后添加的进程,它在postgresql.conf中有一个专门的部分来配置它的行为
    # - Background Writer -

    #bgwriter_delay = 200ms                 # 10-10000ms between rounds
    #bgwriter_lru_maxpages = 100            # max buffers written/round, 0 disables
    #bgwriter_lru_multiplier = 2.0          # 0-10.0 multiplier on buffers scanned/round
    #bgwriter_flush_after = 512kB           # measured in pages, 0 disables
    复制
     
    lbgwriter_delay
    在两次连续刷新数据之间的时间间隔。默认值是200,单位是毫秒。
     
    lbgwriter_lru_maxpages
    BgWriter进程每次写入的最大数据量。以buffers为单位,默认值为100。如果脏数据的量小于这个值,写操作全部由BgWriter进程完成;相反,如果它大于这个值,超过部分将由server process完成。当该值设为0时,表示BgWriter进程被禁用,完全由server process完成;当它被设置为-1时,意味着所有脏数据都由BgWriter进程完成。(这里不包括检查点操作)
    lbgwriter_lru_multiplier
    此参数指示了每次写入磁盘的数据块数,当然,该值必须小于bgwriter_lru_maxpages。如果设置过小,需要写入的脏数据量大于每次写入的数据量,剩下的需要写入磁盘的工作,就需要server processes来完成,这将会降低性能。如果值配置太大,此时写入的脏数据量就会超过所需的缓冲区数量,这虽然便于以后再次应用缓冲区工作,但同时可能会出现IO浪费。这个参数的默认值是2.0。
    lbgwriter_flush_after
    当数据页大小达到bgwriter_flush_after时触发BgWriter,默认值为512KB。

    3. WalWriter进程

    预写日志(也称为Xlog)的核心思想是,对数据文件的修改必须在这些修改被记录到日志中之后才发生,也就是说,在写入数据之前先写入日志。使用这种机制可以避免频繁地向磁盘写入数据,并可以减少磁盘I/O。数据库可以使用这些WAL日志在数据库重启后恢复数据库。WalWriter进程是一个后端进程,它负责确保WAL文件被正确写入磁盘,并且它的行为可以postgresql.conf中设置以下参数进行配置
      #-----------------------------------------------------------------------------
      # WRITE-AHEAD LOG
      #-----------------------------------------------------------------------------
      # - Settings -
      wal_level = logical # minimal, replica, or logical
                                              # (change requires restart)
      #fsync = on                             # flush data to disk for crash safety                                        
      # (turning this off can cause                                        
      # unrecoverable data corruption)#synchronous_commit = on                
      # synchronization level;                                        # off, local, remote_write, remote_apply, or on
      #wal_sync_method = fsync                # the default is the first option                                        
      # supported by the operating system:                                        
                                              #   open_datasync                                        
                                              #   fdatasync (default on Linux)                                        
                                              #   fsync                                        
                                              #   fsync_writethrough                                        
                                              #   open_sync
      #full_page_writes = on                  # recover from partial page writes
      #wal_compression = off                  # enable compression of full-page writes
      #wal_log_hints = off                    # also do full page writes of non-critical updates                                        
      # (change requires restart)#wal_init_zero = on                     # zero-fill new WAL files
      #wal_recycle = on                       # recycle WAL files
      #wal_buffers = -1                       # min 32kB, -1 sets based on shared_buffers                                        
      # (change requires restart)#wal_writer_delay = 200ms               # 1-10000 milliseconds
      #wal_writer_flush_after = 1MB           # measured in pages, 0 disables 
      #commit_delay = 0                       # range 0-100000in microseconds
      #commit_siblings = 5                    # range 1-1000
      复制
      lwal_level
      控制wal存储的级别。wal_level确定有多少信息被写入到WAL。默认值是replica,它添加了WAL归档信息,包括只读服务器(流复制)所需的信息。还可以将其设置为minimal,即只写入从崩溃或立即关闭中恢复所需的信息。设置为Logical允许在逻辑解码场景中完成WAL流。
      lfsync
      这个参数直接控制日志是否先写到磁盘。默认值为ON(先写),这意味着系统应该通过发出wal_sync_method设置的fsync指令,来确保更改确实被刷新到磁盘。虽然关闭fsync通常可以提高性能,但在电源故障或系统崩溃时,这会导致不可恢复的数据损坏。因此,只有当您可以轻松地从外部数据重新创建整个数据库时,才建议关闭fsync。
      lsynchronous_commit
      此参数用于配置系统是否等待WAL完全完成后再将状态信息返回给用户事务。默认值为ON,表示必须等待WAL完成后才能返回事务状态信息;配置OFF可以更快地反馈事务状态。
      lwal_sync_method
      这个参数控制WAL写入磁盘的fsync方法。默认值是fsync。可用的值包括open_datasync、fdatasync、fsync_writethrough、fsync、以及open_sync.open_datasync和open_sync。
      lfull_page_writes
      指示是否将整个页面写入WAL
      lwal_buffers
      指示了用于存储WAL数据的内存空间量。系统默认值为64K。此参数还受wal_writer_delay和commit_delay这两个参数的影响。
      lwal_writer_delay
      WalWriter进程的写入间隔。默认值是200毫秒。如果时间过长,可能会导致WAL缓冲区内存不足;如果时间太短,会导致WAL不断写入,增加磁盘I/O负担。
      lwal_writer_flush_after
      当脏数据超过这个阈值时,它将被刷新到磁盘。
      lcommit_delay
      指示在WAL buffer中存储已提交的数据的时间。默认值为0毫秒,表示没有延迟;
      当它被设置为非零值时,在事务提交后,事务将不会被立即写入到WAL中,但它仍然存储WAL buffer中,等待WalWriter进程定期写入磁盘。
      lcommit_siblings
      当事务发出提交请求时,如果数据库中的事务数量大于commit_sibling的值,事务将等待一段时间(commit_delay值);否则,事务将直接写入到WAL。系统默认值是5,这个参数还确定了commit_delay的有效性。

      4. PgArch进程

      Oracle数据库中的ARCH归档过程类似,区别在于ARCH对重做日志执行归档,而PgArch对WAL日志执行归档。这是必要的,因为WAL日志是会被回收的。换句话说,过去的WAL日志会被新生成的日志覆盖。PgArch进程负责在覆盖WAL日志之前对其进行备份。从版本8.x开始,这些WAL日志可以用于PITR(基于时间点恢复),PITR将数据库状态恢复到特定时间段的特定状态。PgArch在postgresql.conf中也有专门的部分来配置它的行为
        # - Archiving - 

        #archive_mode = off # enables archiving; off, on, or always
        # (change requires restart)
        #archive_command = ''           # command to use to archive a logfile segment                                
                                        # placeholders: %p = path of file to archive                                
                                        #               %f = file name only                                
                                        # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p 
        /mnt/server/archivedir/%f'
        #archive_timeout = 0 # force a logfile segment switch after this
        # number of seconds; 0 disables
        复制
        larchive_mode
        指示是否执行存档操作;可以设置为(off), (on)或(always),默认值是off。
        larchive_command
        管理员为归档WAL日志而设置的命令。在归档命令中,使用预定义变量%p来引用需要存档的WAL完整路径文件名,而%f表示没有路径的文件名(这里的路径是相对于当前工作目录的)。当归档每个WAL segment file时,将执行由archive_command指定的命令。如果archive命令返回0PostgreSQL会认为文件已成功归档,然后删除或回收WAL segment file。如果返回一个非零值,PostgreSQL会认为该文件没有成功存档,并会定期重试,直到成功为止。
        larchive_timeout
        表示归档周期。当超过此参数设置的时间时,将强制切换WAL段。默认值为0(禁用本功能)。

        5. AutoVacuum 进程

        PostgreSQL数据库中,在对数据执行更新或删除操作后,数据库不会立即删除旧版本的数据。相反,数据将被PostgreSQL的多版本机制标记为删除。如果其他事务正在访问这些旧版本的数据,则有必要临时保留它们。在事务被提交后,就不再需要旧版本的数据(死元组),因此数据库需要清理它们以腾出空间。这一任务是通过AutoVacuum 进程来完成的,与AutoVacuum 进程有关的参数也位于postgresql.conf中。
          #-----------------------------------------------------------------------------
          # AUTOVACUUM
          #-----------------------------------------------------------------------------

          #autovacuum = on # Enable autovacuum subprocess? 'on'
                                                  # requires track_counts to also be on.
          #log_autovacuum_min_duration = -1       # -1 disables, 0 logs all actions and
                                                  # their durations, > 0 logs only
          # actions running at least this number
          # of milliseconds.
          #autovacuum_max_workers = 3             # max number of autovacuum
          subprocesses
                                                  # (change requires restart)
          #autovacuum_naptime = 1min # time between autovacuum runs
          #autovacuum_vacuum_threshold = 50       # min number of row updates before
          # vacuum
          #autovacuum_analyze_threshold = 50 # min number of row updates before
          # analyze
          #autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum
          #autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze
          #autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum
          # (change requires restart)
          #autovacuum_multixact_freeze_max_age = 400000000 # maximum multixact age
          # before forced vacuum
          # (change requires restart)
          #autovacuum_vacuum_cost_delay = 2ms # default vacuum cost delay for
          # autovacuum, in milliseconds;
          # -1 means use vacuum_cost_delay
          #autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for
          # autovacuum, -1 means use
          # vacuum_cost_limit
          复制
          lautovacuum
          是否自动启动autovacuum进程,默认值为on。
          llog_autovacuum_min_duration
          此参数记录autovacuum的执行时间。当autovaccum的执行时间超过本参数值时,该事件将记录在日志中。默认值是-1,这意味着没有记录。
          lautovacuum_max_workers
          设置autovacuum subprocesses的最大数量。
          lautovacuum_naptime
          设置两个autovacuum processes之间的间隔时间。
          lautovacuum_vacuum_threshold and autovacuum_analyze_threshold
          设置表中更新元组数量的阈值,如果更新元组数量超过这些值,则需要分别执行vacuumanalyze
          lautovacuum_vacuum_scale_factor and autovacuum_analyze_scale_factor
          设置表大小的scaling factor
          lautovacuum_freeze_max_age
          设置需要被强制清理的数据库的事务ID上限。
          lautovacuum_vacuum_cost_delay
          autovacuum process即将开始执行时,对执行清理成本进行评估。如果autovacuum_vacuum_cost_limit超出了设置的值,那么存在一个由autovacuum_vacuum_cost_delay参数设置的延迟。如果值为-1,则表示改用vacuum_cost_delay的值。默认值为20毫秒。
          lautovacuum_vacuum_cost_limit:
          此值是autovacuum process的评估阈值。默认值为-1,这意味着使用“vacuum_cost_limit”值。如果在执行自动清理进程期间评估的成本超过了autovacuum_vacuum_cost_limit,autovacuum process将处于休眠状态。

          6. Stat Collector

          Stat collector是PostgreSQL数据库的统计信息收集器。它收集数据库操作期间的统计信息,如表的添加、删除或更新的数量、数据块的数量、索引的变化等。收集统计信息主要是为了让查询优化器做出正确的判断,选择最佳的执行计划。postgresql.conf文件中与Stat collector相关的参数如下:
            #------------------------------------------------------------------------------
            # STATISTICS
            #------------------------------------------------------------------------------ 

            # - Query and Index Statistics Collector -
            #track_activities = on
            #track_counts = on
            #track_io_timing = off
            #track_functions = none # none, pl, all
            #track_activity_query_size = 1024 # (change requires restart)
            #stats_temp_directory = 'pg_stat_tmp'
            复制
            ltrack_activities
            指示是否为会话中当前执行的命令启用统计信息收集功能。此参数仅对超级用户和会话所有者可见。默认值是on。
            ltrack_counts
            指示是否为数据库活动启用统计信息收集功能。由于在AutoVacuum自动清理进程中选择了要清理的数据库,需要数据库统计信息,因此该参数的默认值为on。
            ltrack_io_timing
            对调用数据块I/O进行计时,默认为off,因为设置为on状态将反复调用数据库时间,这会增加数据库的大量开销。只有超级用户可以设置
            ltrack_functions
            指示是否启用函数调用数量和耗时统计。
            ltrack_activity_query_size
            设置用于跟踪每个活动会话的当前执行命令的字节数。默认值是1024,只能在数据库启动后设置。
            lstats_temp_directory
            统计信息的临时存储路径。路径可以是相对路径,也可以是绝对路径。默认参数是pg_stat_tmp。此参数只能在postgresql.conf文件或服务器命令行中修改。

            7. Checkpointer 进程

            检查点是由系统设置的事务点序列。设置检查点可以确保检查点之前的WAL日志信息被刷新到磁盘。在发生崩溃时,崩溃恢复过程将查看最新的检查点记录,以确定日志中应该从何处开始REDO操作(称为重做记录)。postgresql.conf文件中的相关参数为:
              # - Checkpoints - 
              #checkpoint_timeout = 5min # range 30s-1d
              max_wal_size = 1GB
              min_wal_size = 80MB#checkpoint_completion_target = 0.5
              # checkpoint target duration, 0.0 - 1.0
              #checkpoint_flush_after = 256kB # measured in pages, 0 disables
              #checkpoint_warning = 30s # 0 disables
              复制
              lcheckpoint_timeout
              此参数配置检查点的执行周期。默认值是5分钟。这意味着每隔5分钟就会出现一个检查点,或者在即将超过max_wal_size时。默认是1 GB
              lmax_wal_size
              此参数设置检查点发生前的WAL的最大值。
              lmin_wal_size
              此参数设置了需要回收的以备将来使用WAL文件总大小的最小值
              lcheckpoint_completion_target
              为了避免大量的页面写入I/O造成冲击,在检查点期间写入脏缓冲区的过程会分散一段时间。该周期由checkpoint_completion_target控制,它是检查点间隔的一部分。
              lcheckpoint_flush_after
              当检查点发生时,检查点写入的页面大小超过本参数值时,将刷新到磁盘。否则,这些页面可能会保存在操作系统的页面缓存中。默认值为256kB
              lcheckpoint_warning
              检查点的操作是非常昂贵的。该参数在检查点之间配置一个阈值,如果由于填充WAL segment files而导致的检查点发生间隔小于本参数值,系统将在服务器日志中输出一个警告,建议用户增加max_wal_size

              8.共享内存和本地内存

              PostgreSQL服务器启动时,将分配一个共享内存作为数据块的缓冲区,以提高读取和写入能力。共享内存中也存在WAL log bufferCLOG buffer。一些全局信息,如进程信息、锁信息、全局统计信息等都存储在共享内存中
              除了共享内存,后台服务还将分配一些本地内存来临时存储不需要全局存储的数据。这些内存缓冲区主要包括以下类别:
              lTemporary buffer:用于访问临时表的本地缓冲区
              lwork_mem:在使用临时磁盘文件之前,内存排序操作和哈希表使用的内存缓冲。
              lmaintenance_work_mem:维护操作中使用的内存缓冲区(例如,acuum, create index, alter table add foreign key等)。

              9.总结

              本文中概述了当今驱动PostgreSQL的核心后端进程,它们是数据库性能调优的基础。可以更改许多参数来影响这些后端进程的行为,以使数据库性能更好,更安全,更快。这将是未来的主题。

              I Love PG
              复制

              关于我们

              PostgreSQLPG2017PostgreSQLPG非盈利行业协会组织。我们致力于在中国PostgreSQLPostgreSQL

              复制

              欢迎投稿

              做你的舞台,show出自己的才华 。

              投稿邮箱:partner@postgresqlchina.com

                                  

                                  ——愿能安放你不羁的灵魂


              技术文章精彩回顾




              PostgreSQL学习的九层宝塔
              PostgreSQL职业发展与学习攻略
              2019,年度数据库舍 PostgreSQL 其谁?
              Postgres是最好的开源软件
              PostgreSQL是世界上最好的数据库
              从Oracle迁移到PostgreSQL的十大理由
              从“非主流”到“潮流”,开源早已值得拥有

              PG活动精彩回顾




              创建PG全球生态!PostgresConf.CN2019大会盛大召开
              首站起航!2019“让PG‘象’前行”上海站成功举行
              走进蓉城丨2019“让PG‘象’前行”成都站成功举行
              中国PG象牙塔计划发布,首批合作高校授牌仪式在天津举行
              群英论道聚北京,共话PostgreSQL
              相聚巴厘岛| PG Conf.Asia 2019  DAY0、DAY1简报
              相知巴厘岛| PG Conf.Asia 2019 DAY2简报
              独家|硅谷Postgres大会简报
              直播回顾 | Bruce Momjian:原生分布式将在PG 14版本发布

              PG培训认证精彩回顾




              中国首批PGCA认证考试圆满结束,203位考生成功获得认证!
              中国第二批PGCA认证考试圆满结束,115位考生喜获认证!
              重要通知:三方共建,中国PostgreSQL认证权威升级!
              近500人参与!首次PGCE中级、第三批次PGCA初级认证考试落幕!
              2020年首批 | 中国PostgreSQL初级认证考试圆满结束
              一分耕耘一分收获,第五批次PostgreSQL认证考试成绩公布

              复制
              文章转载自开源软件联盟PostgreSQL分会,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论