这篇博文是关于postgres一个鲜为人知的’特性’:当登录到postgres数据库时发生的pg_internal.init文件(多个)的加载或创建。
因为YugabyteDB重用postgres源,YugabyDB执行与postgres相同的pg_internal.init文件处理。
让我先谈谈为什么要写这篇文章。
在测试中,我注意到首次连接postgres比持续连接花费更多的时间。这点很容易忽视,因为当我再次测试时,我就再也没看到此情况了。那么当postmaster再次启动时,第一次连接再次显示了更高的延迟。这意味着在特定情况下,
即如果这些数据库处理的是在postmaster启动之后访问的数据库,则可能会执行额外的工作,从而增加登录延迟。在新创建或者已创建的数据库上做自动化测试是很重要的。
在深入细节前:postgres/YugabyteDB并发访问重要吗,它会影响正常的数据库活动吗?不会(!)
执行额外的工作去创建pg_internal.init文件的现象只会在第一个后台进程登录一个给定的postmaster数据库时发生。所以,这篇文章重要在哪里,就是写这篇文章的原因。延迟测试是很重要的,有助于理解这个明显的异常。
与登录的延迟差异密切相关:第一个连接延迟被数据库中的对象数所影响,并且随着对象数量的增加(相对于处理能力~>1000)而变得重要,YugabyteDB比原始postgres在此方面更敏感,YugabyteDB从主leader中加载目录数据,而原始postgres从本地文件或者缓存cache中获取目录数据。
所以,这会发生什么呢?
在postgres中,登录数据库时,postmaster会fork后端进程,后端进程在私有内存中创建cache。更准确的说:每一个独立的后端进程通过所需的最小目录数据在私有内存中创建cache,所以它有足够的目录数据来运行。
作为后端进程创建的一部分,它创建的cache叫做’relcache’或者元组缓存,这些缓存包含了元组描述符。这些描述符是非常全面的,这也解释了为什么postmaster启动后第一个会话进入数据库后会收集全局relcache信息,收集本地数据库指定的relcache信息,并将这些信息写入内存格式的文件中。这样,任意后续的会话都可以利用这个文件去加载会话的relcache,无需执行获取relcache中每个关系的所有信息的工作。
再者:如果你有一套正在运行的postgres或者YugabyteDB数据库集群,这种现象不应该会影响正常的每日操作。
但是,在特定的情况下,例如在构建之后小心地计时登录,这一点非常重要,因为第一次登录将有更高的延迟。
为了能理解pg_internal.init文件的创建影响,你可以使用connection-profiler对象(https://github.com/fritshoogland-yugabyte/connection-profiler.git)。
安装connection-profiler
为了安装connection-profiler,你需要rust来编译connection-profiler,你需要git来克隆connection-profiler对象。
获取git和gcc
sudo yum install git gcc -y
克隆connection-profiler仓库
git clone https://github.com/fritshoogland-yugabyte/connection-profiler.git
获取rust
curl https://sh.rustup.rs -sSf | sh -s -- -y
Source rust环境
source "$HOME/.cargo/env"
进入connection-profiler文件夹并且创建二进制产品(版本)
cd connection-profiler
cargo build --release
一旦完成,在target/release文件夹下有一个connection-profiler的可执行文件。
PostgreSQL
postgres启动postmaster测试。希望从描述中可以清楚地看到:在测试前,不要连接任何客户端。否则该客户端将执行pginternal.init文件的初始化。
现在,通过执行若干(5)个连接而不执行任何SQL来运行连接connection-profiler:
[postgres@localhost connection-profiler]$ ./target/release/connection-profiler -u "user=postgres password=postgres port=5432 host=localhost" -q '' -n 5
create_connection 5001 us
------------------------------------------------------------
============================================================
create_connection 2724 us
------------------------------------------------------------
============================================================
create_connection 2523 us
------------------------------------------------------------
============================================================
create_connection 2365 us
------------------------------------------------------------
============================================================
create_connection 2380 us
------------------------------------------------------------
============================================================
很明显,第一次连接明显比其他连接慢。如果重复5次相同的连接序列,则第一次连接不会再次显示较高的延迟:
[postgres@localhost connection-profiler]$ ./target/release/connection-profiler -u "user=postgres password=postgres port=5432 host=localhost" -q '' -n 5
create_connection 2602 us
------------------------------------------------------------
============================================================
create_connection 3074 us
------------------------------------------------------------
============================================================
create_connection 2799 us
------------------------------------------------------------
============================================================
create_connection 2319 us
------------------------------------------------------------
============================================================
create_connection 2503 us
------------------------------------------------------------
============================================================
YugabyteDB
YugabyteDB使用了postgres的源码,所以会有相同的行为。而YugabyteDB和postgres相比,最主要的不同在于存储变换到网络资源上。
这就有了很多的灵活性和可扩展性。但同时也意味着引入了额外的延迟。这就是基于本地虚拟机的小型集群上的延迟情况。
[vagrant@yb-1 connection-profiler]$ ./target/release/connection-profiler -u "user=yugabyte password=yugabyte port=5433 host=localhost" -q '' -n 5
create_connection 187654 us
------------------------------------------------------------
============================================================
create_connection 22404 us
------------------------------------------------------------
============================================================
create_connection 17495 us
------------------------------------------------------------
============================================================
create_connection 17815 us
------------------------------------------------------------
============================================================
create_connection 18213 us
------------------------------------------------------------
============================================================
重做重复的连接可以提供更一致的响应时间:
[vagrant@yb-1 connection-profiler]$ ./target/release/connection-profiler -u "user=yugabyte password=yugabyte port=5433 host=localhost" -q '' -n 5
------------------------------------------------------------
============================================================
create_connection 18996 us
------------------------------------------------------------
============================================================
create_connection 19581 us
------------------------------------------------------------
============================================================
create_connection 21980 us
------------------------------------------------------------
============================================================
create_connection 21924 us
------------------------------------------------------------
============================================================
这就表明:更高的延迟是我们正在努力改进的事情,尽管它与本地postgres延迟相差不远。
基于创建pg_internal.init文件的第一个连接将请求目录数据来创建这些这是对其本地tablet服务器中的代理线程完成的,然后该代理线程向当前主领导执行RPC请求以获取实际的目录数据。
原文标题:Postgres first database connection latency
原文作者:Frits Hoogland
原文链接:https://dev.to/yugabyte/postgres-first-database-connection-latency-4fdh




