UXDB有时可能耗尽各种操作系统的资源上限,尤其是多个服务器副本在同一个系统上运行时。本节说明UXDB使用的内核资源和解决内核资源消耗有关问题可以采取的方法。
UXDB需要操作系统提供进程间通信(IPC)特性,特别是共享内存和信号量。Unix驱动的系统通常提供 “System V” IPC、 “POSIX” IPC,或者两者都有。 Windows这些功能有它自己的的实现方法,不做讨论。
完全缺少这些功能通常表现为服务器启动时的“illegal system call”错误。这种情况下,除了重新配置内核之外别无选择。UXDB没有这些功能将无法工作。不过,在现代操作系统中这种情况是罕见的。
在启动服务器时,UXDB通常分配少量的System V共享内存, 和大量的POSIX (mmap)共享内存。另外, 在服务器启动时会创建大量信号量,这些信号量可以是System V或POSIX风格。 目前,POSIX信号量用于Linux和FreeBSD系统,其他平台则使用System V信号量。
System V IPC特性通常受系统范围分配限制的约束。当UXDB超出了这些限制之一时,服务器会拒绝启动并且并且留下一条有指导性的错误消息,其中描述了问题以及应该怎么做(又见第?2.2.2?节)。相关的内核参数在不同系统之间的命名方式一致,表?2.1给出了一个概述。不过,设置它们的方法多种多样。下面还给出了对于某些平台的建议:
表?2.1.?System V IPC参数
名称 | 描述 | 合理取值(运行一个UXDB实例) |
---|---|---|
SHMMAX | 共享内存段的最大尺寸(字节) | 至少1kB,但是默认值通常要高一些 |
SHMMIN | 共享内存段的最小尺寸(字节) | 1 |
SHMALL | 可用共享内存的总量(字节或页面) | 如果是字节,同SHMMAX ;如果是页面,
为ceil(SHMMAX/PAGE_SIZE) ,加上其他应用程序的空间 |
SHMSEG | 每个进程的最大共享内存段数目 | 只需要1段,但是默认值高很多 |
SHMMNI | 系统范围内的最大共享内存段数目 | SHMSEG 外加其他应用的空间 |
SEMMNI | 信号量标识符(即集合)的最大数目 | 至少ceil((max_connections + autovacuum_max_workers + max_worker_processes + 5) / 16) 加上其他应用程序的空间 |
SEMMNS | 系统范围内的最大信号量数目 | ceil((max_connections + autovacuum_max_workers + max_worker_processes + 5) / 16) * 17 外加其他应用的空间 |
SEMMSL | 每个集合中信号量的最大数目 | 至少17 |
SEMMAP | 信号量映射中的项数 | 见文本 |
SEMVMX | 信号量的最大值 | 至少1000 (默认值常常是32767,如非必要不要更改) |
UXDB要求少量字节的System V共享内存(在64位平台上通常是48字节)用于每一个服务器拷贝。在大多数现代操作系统上,这个量很容易得到。但是,如果你运行了很多个服务器拷贝,或者其他应用也在使用System V共享内存,可能需要增加SHMALL(系统范围内System V共享内存的总量)。注意在很多系统上SHMALL是以页面而不是字节来度量。
不太可能出问题的是共享内存段的最小尺寸(SHMMIN),对UXDB来说应该最多大约是32字节(通常只是1)。而系统范围(SHMMNI)或每个进程(SHMSEG)的最大共享内存段数目不太可能会导致问题,除非系统把它们设成零。
当使用System V信号量时,UXDB对每个允许的连接(max_connections)、每个允许的自动清理工作者进程(autovacuum_max_workers)和每个允许的后台进程(max_worker_processes)各使用一个信号量,以16个为一个集合。每个集合还要增加第17个信号量,用于存储“magic number”,以检测和其它应用使用的信号量集合的冲突。系统里的最大信号量数目是由SEMMNS设置的,因此这个值必须至少和max_connections加autovacuum_max_workers再加max_worker_processes一样大,并且每16个工作者还要另外加一个(见表?2.1中的公式)。参数SEMMNI决定系统中同一时刻可以存在的信号量集合的数目限制。因此这个参数必须至少为ceil((max_connections + autovacuum_max_workers + max_worker_processes + 5) / 16)。当允许连接数目大于SEMMNI时,服务器启动失败,错误消息会提示"No space left on device",这个提示比较有迷惑性,是来自函数semget的响应。实际上只需降低允许连接数,使之小于SEMMNI,便可正常启动。
在某些情况下可能还有必要增大SEMMAP,使之至少与SEMMNS相近。这个参数定义信号量资源映射的尺寸,在其中每个连续的可用信号量块都需要一项。每当一个信号量集合被释放,那么它要么会被加入到与该被释放块相邻的一个现有项,或者它会被注册在一个新映射项中。如果映射被填满,被释放的信号量将丢失(直到重启)。因此信号量空间的碎片时间过长会导致可用的信号量比应有的信号量少。
与“semaphore undo”有关的其他各种设置,如SEMMNU
和SEMUME
不会影响UXDB。
当使用POSIX信号量时,所需的信号量数量与System V相同,即每个允许的连接(max_connections)、允许的自动清理工作进程(autovacuum_max_workers)和允许的后台进程(max_worker_processes)一个信号量。在首选此选项的平台上,POSIX信号量的数量没有特定的内核限制。
默认的最大段尺寸是32MB,并且默认的最大总尺寸是2097152个页面。一个页面通常是4096字节,而带有“huge pages”的特殊内核配置(使用getconf PAGE_SIZE
来验证)除外。
共享内存尺寸设置可以通过sysctl
接口来更改。例如,要允许16GB:
$
sysctl -w kernel.shmmax=17179869184
$
sysctl -w kernel.shmall=4194304
为保证这些设置在重启后保持有效,推荐将这些设置放到/etc/sysctl.conf
中。
老版本里可能没有sysctl
程序,但是同样的改变可以通过操作/proc
文件系统来做:
$
echo 17179869184 >/proc/sys/kernel/shmmax
$
echo 4194304 >/proc/sys/kernel/shmall
剩下的参数默认大小已经够用,通常不需要改变。
Unix类系统强制很多资源限制,这些限制可能干扰UXDB服务器的运行。这里尤其重要是对每个用户的进程数目、每个进程打开文件数目、以及每个进程可用内存的限制。这些限制中每个都有一个“硬”限制和一个“软”限制。实际使用的是软限制,但用户可以自己修改成最大为硬限制的数目。而硬限制只能由root用户修改。系统调用setrlimit
负责设置这些参数。 shell的内建命令ulimit
(Bourne shells)或limit
(csh)是用于在命令行上控制资源限制的。相关的参数是maxproc
、openfiles
和datasize
。例如:
default:\ ... :datasize-cur=256M:\ :maxproc-cur=256:\ :openfiles-cur=256:\ ...
(-cur
是软限制。增加-max
可设置硬限制)。
内核也可以在某些资源上有系统范围的限制。
在Linux上,/proc/sys/fs/file-max
决定内核支持打开的最大文件数。可以通过往该文件写入一个不同的数值修改此值,或者在/etc/sysctl.conf
里增加一个赋值来修改。每个进程的最大打开文件限制是在编译内核时进行修改。
UXDB服务器每个连接都使用一个进程,所以应该至少允许和连接数相同的进程数,再加上系统其它部分所需要的进程数目。通常这个并不是什么问题,但如果在一台机器上运行多个服务器,资源使用可能就会紧张。
打开文件数目的出厂默认设置通常设置为“socially friendly”数值, 它允许许多用户在一台机器上共存,而不会导致不成比例的系统资源使用。一般情况下,你可以在一台机器上上运行很多服务器,但是在一些特殊情况下,可能需要提高这个限制。
一些系统允许独立的进程打开非常多的文件;如果有几个进程这样做,系统范围的上限很容易达到。如果发现这种情况,而且不想修改系统范围的限制,可以设置UXDB的max_files_per_process配置参数来限制打开文件数的消耗。
在Linux 2.4及其后的版本中,默认的虚拟内存行为对UXDB不是最优的。由于内核实现内存过量使用的方法,如果UXDB或其它进程的内存要求导致系统用光虚拟内存,那么内核可能会终止UXDB的uxmaster进程(主服务器进程)。
如果出现这种情况,会出现如下内核消息:
Out of Memory: Killed process 12345 (uxdb).
这表明uxdb
进程因为内存不足而被终止。尽管现有的数据库连接将继续正常运转,但是将无法接受新的连接。要想恢复,应该重启UXDB。
避免这个问题的方法是在一台确保不会因为其它进程而耗尽内存的机器上运行UXDB。 如果内存紧张,增加操作系统的交换空间有助于避免这个问题,因为OOM(out-of-memory)killer只有在物理内存和交换空间都耗尽时才会被调用。
如果UXDB本身是系统内存耗尽的原因,你可以通过改变你的配置来避免该问题。在某些情况中,降低内存相关的配置参数可能有所帮助,特别是shared_buffers
和work_mem
两个参数。在其他情况中,允许太多连接到数据库服务器本身也可能导致该问题。在很多情况下,最好减小max_connections
并且转而利用外部连接池软件。
在Linux 2.6及其后的版本中,可以修改内核的行为,可以避免“过量使用”内存。尽管此设置不会阻止OOM killer被调用,但它可以显著地降低其可能性并且将因此使系统更加稳定。这可以通过用sysctl
选择严格的过量使用模式来实现:
sysctl -w vm.overcommit_memory=2
或者在/etc/sysctl.conf
中写入一个等效配置语句。可能还需要修改相关的设置vm.overcommit_ratio
。详细信息请参阅内核文档的https://www.kernel.org/doc/Documentation/vm/overcommit-accounting文件。
另外一种方法,不管改变或不改变vm.overcommit_memory
都可以使用,它将uxmaster进程的进程相关的OOM score adjustment值设置为-1000
,从而保证它不会成为OOM killer的目标。这样做最简单的方法是在uxmaster的启动脚本中执行
echo -1000 > /proc/self/oom_score_adj
并且要在调用uxmaster之前执行。请注意这个动作必须以root完成,否则它将不会产生效果。所以把这个放在启动脚本中,并将脚本所属权限改为root,以root执行是最方便的。如果这样做,还应该在调用uxmaster之前在启动脚本中设置这些环境变量:
export UX_OOM_ADJUST_FILE=/proc/self/oom_score_adj export UX_OOM_ADJUST_VALUE=0
这些设置将导致uxmaster子进程使用值为零的OOM score adjustment运行,所以OOM killer仍能在需要时把它们作为目标。如果你想要子进程用某些其他OOM score adjustment值运行,可以为UX_OOM_ADJUST_VALUE
使用其他的值(UX_OOM_ADJUST_VALUE
被省略时默认为零)。如果你没有设置UX_OOM_ADJUST_FILE
,子进程将使用和uxmaster相同的OOM score adjustment运行,这是不明智的,因为重点是确保uxmaster具有优先的设置。
更老的Linux内核不提供/proc/self/oom_score_adj
,但是可能有一个具有相同功能的早期版本,被称为/proc/self/oom_adj
。除了禁用值是-17
而不是-1000
。相应的UXDB的编译宏定义为-DLINUX_OOM_ADJ=0。
有些厂商的Linux 2.4内核被报告有着2.6过量使用sysctl
参数的早期版本。不过,在没有相关代码的2.4内核里设置vm.overcommit_memory
为2将会让事情更糟。推荐检查一下实际的内核源代码(见文件mm/mmap.c
中的vm_enough_memory
函数),验证一下这个是在内核中是被支持的,然后再在2.4安装中使用它。文档文件overcommit-accounting
的存在不能当作是这个特性存在的证明。
当UXDB使用大量连续的内存块时,可以使用Huge Pages减少开销,特别是在使用shared_buffers时。
要在UXDB中使用此特性,内核设置需要满足
CONFIG_HUGETLBFS=y
和CONFIG_HUGETLB_PAGE=y
。
还必须调整内核设置vm.nr_hugepages
。估计所需Huge Pages的数量,
请启动UXDB,而不启用Huge Pages,并使用
/proc
文件系统来检查uxmaster的VmPeak
值以及系统的Huge Pages大小。
这可能看起来像:
$head -1 $UXDATA/uxmaster.pid
4170 $grep ^VmPeak /proc/4170/status
VmPeak: 6490428 kB $grep ^Hugepagesize /proc/meminfo
Hugepagesize: 2048 kB
6490428
/ 2048
大约是3169.154
,因此在这个示例中至少需要
3170
个Huge Pages,澳门游戏平台注册网站可以设置:
$ sysctl -w vm.nr_hugepages=3170
如果机器上的其他程序也需要Huge Pages,则需要设置更大的值。
还要将此设置添加到/etc/sysctl.conf
,
以便在重启后重新应用它。
有时候内核会无法立即分配想要数量的Huge Pages,所以可能有必要重复该命令或者重新启动。 (在重新启动之后,应立即将内存转换为Huge Pages。) 要验证Huge Pages分配情况,请使用:
$ grep Huge /proc/meminfo
可能还需要赋予数据库服务器的操作系统用户权限,可以通过sysctl
设置vm.hugetlb_shm_group
以使用Huge Pages,
或赋予使用ulimit -l
锁定内存的权限。
UXDB中,通常尽可能使用Huge Pages并且在失败时转回到正常页面。要强制使用Huge Pages,你可
以在uxsinodb.conf
中把huge_pages设置成
on
。注意此设置下如果没有足够的Huge Pages可用,
UXDB将会启动失败。
Linux大页面特性的详细描述可见https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt.