了解postgreSQL共享内存

时间:2015-10-04 06:44:49

标签: sql postgresql

我已经看过presentation,但仍然有一个关于共享缓冲区工作的问题。如幻灯片16所示,当服务器处理传入请求时,postmaster进程调用fork()以创建用于处理传入请求的子进程。这是一张照片: enter image description here

因此,我们拥有postmaster流程的完整副本,但pid除外。现在,如果子进程更新属于共享内存的某些数据(放入共享缓冲区,如幻灯片17所示),我们需要其他线程知道这些更改。图片:

enter image description here

同步化过程是我不理解的。任何进程都拥有共享内存的副本,并且在复制时不知道另一个线程是否 某些东西到其共享内存的副本。如果在通过调用proc1创建fork()之后,稍后会创建另一个进程proc2并开始在其共享内存副本中写入内容。

问题: proc1如何知道如何处理由proc2修改的共享内存部分?

2 个答案:

答案 0 :(得分:6)

要理解的关键是使用两种不同类型的内存共享

一个是fork()(没有exec())使用的写时复制共享,其中子进程继承父进程的内存和状态。在这种情况下,当子或父修改任何内容时,将分配修改的内存页面的新私有副本。因此,孩子在fork()之后看不到父母做出的更改,而且父母在fork()之后看不到孩子所做的更改。同龄儿童也看不到对方的变化。就记忆而言,它们都是孤立的,它们只是共享一个共同的祖先。

该记忆是图中Program (text)datastack部分的显示内容。

由于该isoltion,PostgreSQL 使用POSIX共享内存 - 或者在旧版本中使用系统V共享内存。这些是显式共享的内存段,映射到一系列地址。每个进程都看到相同的内存,而不是 copy-on-write。它完全读/写共享。

这是紫色"共享内存中显示的内容"图的一部分。

POSIX共享内存用于进程间通信以进行锁定,对于shared_buffers等等。不是从fork()继承的内存。

虽然来自fork的内存通常是共享写时复制,但这实际上是一个操作系统实现细节。操作系统可以选择不共享它,并在fork时立即复制父母的整个地址空间。写拷贝共享真正相关的唯一方法是查看top等。

当PostgreSQL引用"共享内存"它总是在谈论映射到每个进程的地址空间的POSIX或System V共享内存块。不是来自fork()的写时共享。

答案 1 :(得分:1)

我不知道这个特殊情况,但通常在linux和大多数其他操作系统中为了加速创建新进程,当一个进程要求操作系统创建一个新进程然后OS创建一个新进程最低要求(特别是在数据库应用程序中)并与子共享大部分父内存空间。现在,当孩子想要修改共享内存的某些部分时,OS使用COW(写入时复制)概念并为子进程使用创建该部分内存的新副本。因此,此部分特定于子进程,不再与父进程共享。