人大金仓 (Kingbase) 数据库 /dev/shm 问题分析文档
·
目录标题
人大金仓 (Kingbase) 数据库 /dev/shm 问题分析文档
目录
1. 问题现象
1.1 典型错误信息
ERROR: could not resize shared memory segment "/kingbase.xxx" to xx bytes: No space left on device
1.2 问题影响
- 数据库服务无法启动
- 已运行的数据库连接中断
- 业务系统无法正常访问数据库
- 数据库性能下降(如果勉强运行)
2. 错误原因分析
2.1 容器默认 /dev/shm 大小限制
Kubernetes 容器中 /dev/shm 的默认大小仅为 64MB:
# 查看容器内 /dev/shm
$ df -h /dev/shm
Filesystem Size Used Avail Use% Mounted on
shm 64M 16K 64M 1% /dev/shm
# 查看实际挂载参数
$ cat /proc/mounts | grep shm
shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)
# ↑ 默认只有 64MB
2.2 Kingbase 为什么需要共享内存
Kingbase(基于 PostgreSQL 内核)使用共享内存用于:
| 用途 | 说明 | 内存占用估算 |
|---|---|---|
| 共享缓冲区 (Shared Buffers) | 数据页缓存 | shared_buffers × 8KB |
| WAL 缓冲区 | 事务日志缓冲 | wal_buffers × 8KB |
| 锁管理器 | 表锁、行锁等 | 约 max_connections × 500KB |
| 进程间通信 | 信号量、消息队列 | 数 MB |
| 查询工作内存 | 排序、哈希等临时操作 | work_mem × 活跃查询数 |
2.3 为什么会报错 “No space left on device”
即使只是尝试分配 1MB,也会报错的原因:
- 已有共享内存段占用空间 - Kingbase 启动时已分配了多个共享内存段
- 累积效应 - 多个连接、多次分配累积超过 64MB
- 配置参数过大 -
shared_buffers、max_connections等参数配置较高
典型 Kingbase 配置的共享内存需求:
shared_buffers = 128MB # 约 131072 个 8KB 页
max_connections = 200 # 约 100MB 用于锁管理
work_mem = 4MB # 每个查询最多 4MB
wal_buffers = 16MB # WAL 缓冲区
--------------------------------
总需求:约 300-500MB+
结论:默认 64MB 的 /dev/shm 远远不够!
3. 技术背景
3.1 容器 /dev/shm 挂载方式
默认方式(64MB)
# 未配置 dshm 卷时,容器使用默认 sandbox shm
# 挂载点:/run/containerd/io.containerd.grpc.v1.cri/sandboxes/<id>/shm
# 大小固定:64MB
实际挂载示例
# 查看宿主机上的容器 shm 挂载
$ mount | grep containerd
shm on /run/containerd/io.containerd.grpc.v1.cri/sandboxes/.../shm \
tmpfs rw,nosuid,nodev,noexec,relatime,size=65536k
# ↑ 容器默认 shm,只有 64MB
# 对比:配置了 dshm 的 pod
tmpfs on /var/lib/kubelet/pods/<pod-id>/volumes/kubernetes.io~empty-dir/dshm \
tmpfs rw,relatime,size=130501340k
# ↑ 通过 emptyDir 创建的 dshm,约 125GB
3.2 Kubernetes 中的三种挂载方式
| 方式 | 配置 | 大小 | 适用场景 |
|---|---|---|---|
| 默认 | 无配置 | 64MB | 小内存应用 |
| emptyDir + Memory | 见下文 | 自定义 | 数据库等需大 shm |
| hostPath | 挂载宿主机 /dev/shm | 继承宿主机 | 需跨容器共享 |
4. 解决方案
4.1 方案一:配置 emptyDir(推荐)
适用于 KingbaseCluster CRD
apiVersion: qfusion.irds.io/v1alpha1
kind: KingbaseCluster
metadata:
name: kingbase-53e4bf90
namespace: qfusion-admin
spec:
# 其他配置...
# 添加 Pod 模板配置
podTemplate:
spec:
containers:
- name: kingbase
# 挂载扩容的 /dev/shm
volumeMounts:
- mountPath: /dev/shm
name: dshm
volumes:
- name: dshm
emptyDir:
medium: Memory # 使用内存作为存储介质
sizeLimit: 512Mi # 设置大小为 512MB
适用于普通 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: kingbase
spec:
template:
spec:
containers:
- name: kingbase
image: kingbase-v8r6:v4.1.2
volumeMounts:
- mountPath: /dev/shm
name: dshm
volumes:
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 512Mi
4.2 方案二:降低 Kingbase 共享内存参数
如果不方便修改 Kubernetes 配置,可以降低数据库参数:
-- 连接到数据库
ALTER SYSTEM SET shared_buffers = '32MB'; -- 降低共享缓冲区
ALTER SYSTEM SET max_connections = 50; -- 降低最大连接数
ALTER SYSTEM SET work_mem = '1MB'; -- 降低工作内存
ALTER SYSTEM SET wal_buffers = '4MB'; -- 降低 WAL 缓冲区
-- 重启数据库使配置生效
SELECT pg_reload_conf();
注意:这种方式会影响数据库性能,仅作为临时解决方案。
4.3 方案三:使用 hostPath(不推荐)
volumes:
- name: dshm
hostPath:
path: /dev/shm
缺点:
- 安全性较低
- 所有容器共享同一块 shm
- 不适合生产环境
5. 推荐配置
5.1 根据 Kingbase 参数计算所需 /dev/shm 大小
#!/bin/bash
# 计算 Kingbase 所需的 /dev/shm 大小
# 获取配置(假设已连接数据库)
SHARED_BUFFERS=$(ksql -t -c "SHOW shared_buffers" | awk '{print $2}')
MAX_CONN=$(ksql -t -c "SHOW max_connections" | awk '{print $2}')
WORK_MEM=$(ksql -t -c "SHOW work_mem" | awk '{print $2}')
WAL_BUFFERS=$(ksql -t -c "SHOW wal_buffers" | awk '{print $2}')
# 转换单位为 MB
function to_mb() {
echo $1 | sed 's/MB//;s/GB/*1024/' | bc
}
# 估算总需求
SHM_SIZE=$((
$(to_mb $SHARED_BUFFERS) +
$(to_mb $WAL_BUFFERS) +
MAX_CONN * 1 +
$(to_mb $WORK_MEM) * 10
))
# 建议大小(留 50% 余量)
RECOMMENDED=$((SHM_SIZE * 3 / 2))
echo "推荐 /dev/shm 大小: ${RECOMMENDED}MB"
5.2 推荐配置表
| 场景 | shared_buffers | max_connections | 推荐 /dev/shm |
|---|---|---|---|
| 开发测试 | 32MB | 50 | 256Mi |
| 小型生产 | 128MB | 100 | 512Mi |
| 中型生产 | 256MB | 200 | 1Gi |
| 大型生产 | 512MB+ | 300+ | 2Gi+ |
6. 验证方法
6.1 检查当前 /dev/shm 使用情况
# 在容器内执行
df -h /dev/shm
# 查看共享内存段详情
ipcs -m
# 查看 /dev/shm 下的文件
ls -lh /dev/shm/
6.2 检查 Pod 挂载配置
# 查看 Pod 的 volume 挂载情况
kubectl get pod <pod-name> -n qfusion-admin -o jsonpath='{.spec.volumes[*]}'
# 查看容器内的挂载点
kubectl exec -it <pod-name> -n qfusion-admin -- df -h
6.3 测试共享内存分配
# 在容器内创建测试文件
dd if=/dev/zero of=/dev/shm/test bs=1M count=100
# 如果成功写入 100MB,说明 /dev/shm 至少有 100MB 可用空间
# 清理测试文件
rm /dev/shm/test
6.4 验证 Kingbase 共享内存使用
-- 查看共享缓冲区大小
SHOW shared_buffers;
-- 查看当前共享内存使用情况
SELECT * FROM pg_stat_sharing;
-- 查看活跃连接数
SELECT count(*) FROM pg_stat_activity;
7. 故障排查检查清单
- 检查容器内
df -h /dev/shm输出 - 检查 Pod 是否配置了 dshm emptyDir 卷
- 检查 Kingbase 的 shared_buffers 参数
- 检查 Kingbase 的 max_connections 参数
- 使用
ipcs -m查看共享内存段使用情况 - 检查数据库日志中的相关错误信息
- 确认 emptyDir 的 sizeLimit 是否足够
8. 附录
8.1 相关错误代码
| 错误代码 | 含义 | 解决方案 |
|---|---|---|
| ENOSPC | No space left on device | 扩容 /dev/shm |
| EINVAL | Invalid argument | 检查 sizeLimit 格式 |
| EPERM | Operation not permitted | 检查 Pod 安全策略 |
8.2 参考资料
文档版本: 1.0
创建日期: 2026-01-06
适用于: Kingbase V8R6, QFusion 4.1.2+
更多推荐




所有评论(0)