WSL创建pgsql容器脚本
因为有一个特殊的配置做实验用
shell
#!/bin/bash
# ========================
# PostgreSQL 18 重新创建脚本
# 修复挂载路径问题
# ========================
echo "开始重新创建 PostgreSQL 18 容器..."
# 停止并删除旧容器
echo "停止并删除旧容器..."
docker stop postgres18 2>/dev/null || true
docker rm postgres18 2>/dev/null || true
# 删除旧的 volume(可选)
read -p "是否删除旧的 volume? (y/N): " DELETE_VOLUME
if [[ $DELETE_VOLUME == "y" || $DELETE_VOLUME == "Y" ]]; then
docker volume rm postgres_data_18 2>/dev/null || true
docker volume rm postgres_logs_18 2>/dev/null || true
fi
# 创建 docker volume
echo "创建 docker volume..."
docker volume create postgres_data_18 2>/dev/null || true
docker volume create postgres_logs_18 2>/dev/null || true
# 创建本地配置文件目录
echo "创建配置文件目录..."
mkdir -p ./postgres-config
# 创建优化配置文件
echo "生成 PostgreSQL 配置文件..."
cat << 'EOF' > ./postgres-config/postgresql.conf
# ========================
# PostgreSQL 18 优化配置
# 针对 WSL2 + Docker 环境
# ========================
# 基础配置
listen_addresses = '*' # 监听所有地址
port = 5432 # 默认端口
max_connections = 100 # 限制连接数
# 内存配置
shared_buffers = 2GB # 增加到 2GB (建议系统内存的25%)
effective_cache_size = 4GB # 增加到 4GB (建议系统内存的50%)
work_mem = 32MB # 增加工作内存 (每个排序/哈希操作)
maintenance_work_mem = 512MB # 增加维护内存 (VACUUM, CREATE INDEX等)
# WAL 和检查点优化
wal_level = replica # 默认级别,支持复制
wal_buffers = 32MB # 增加 WAL 缓冲区
wal_writer_delay = 200ms # 减少 WAL 写入延迟
wal_writer_flush_after = 1MB # 调整刷新阈值
checkpoint_timeout = 15min # 减少检查点间隔
checkpoint_completion_target = 0.9 # 保持平滑检查点
max_wal_size = 8GB # 增加最大 WAL 大小
min_wal_size = 2GB # 增加最小 WAL 大小
# 写入性能优化
synchronous_commit = off # 关闭同步提交(提高性能,有微小数据丢失风险)
fsync = on # 保持数据安全
full_page_writes = on # 保持完整页写入
wal_compression = on # 开启 WAL 压缩
wal_log_hints = on # 开启 WAL 提示
# I/O 优化 (SSD)
random_page_cost = 1.1 # SSD 优化
effective_io_concurrency = 200 # 提高 I/O 并发
seq_page_cost = 1.0 # 顺序页面成本
# 查询优化
default_statistics_target = 100 # 增加统计信息目标
constraint_exclusion = partition # 约束排除
cursor_tuple_fraction = 0.1 # 游标元组分数
# 日志配置
logging_collector = on # 开启日志收集
log_directory = '/var/log/postgresql' # 日志目录
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = 1d # 每天轮换
log_rotation_size = 100MB # 100MB轮换
log_min_duration_statement = 1000 # 记录执行超过1秒的语句
# 性能监控
track_activities = on # 跟踪活动
track_counts = on # 跟踪计数
track_io_timing = on # 跟踪I/O时间
track_functions = pl # 跟踪PL函数
# 自动清理
autovacuum = on # 开启自动清理
autovacuum_max_workers = 3 # 自动清理最大工作进程
autovacuum_naptime = 1min # 自动清理间隔
autovacuum_vacuum_threshold = 50 # 清理阈值
autovacuum_analyze_threshold = 50 # 分析阈值
autovacuum_vacuum_scale_factor = 0.2 # 清理比例因子
autovacuum_analyze_scale_factor = 0.1 # 分析比例因子
# 时区和本地化
timezone = 'Asia/Shanghai' # 设置时区
lc_messages = 'en_US.UTF-8' # 消息语言
lc_monetary = 'en_US.UTF-8' # 货币格式
lc_numeric = 'en_US.UTF-8' # 数字格式
lc_time = 'en_US.UTF-8' # 时间格式
# 客户端连接
client_min_messages = notice # 客户端最小消息级别
log_min_messages = warning # 日志最小消息级别
log_checkpoints = on # 记录检查点
log_connections = on # 记录连接
log_disconnections = on # 记录断开连接
log_lock_waits = on # 记录锁等待
log_temp_files = 0 # 记录临时文件
# 其他
deadlock_timeout = 1s # 死锁超时时间
max_locks_per_transaction = 64 # 每个事务的最大锁数
EOF
# 启动 PostgreSQL 18 容器
echo "启动 PostgreSQL 18 容器..."
docker run -d \
--name postgres18 \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_USER=postgres \
-e POSTGRES_DB=postgres \
-v postgres_data_18:/var/lib/postgresql \
-v ./postgres-config/postgresql.conf:/etc/postgresql/postgresql.conf \
-v postgres_logs_18:/var/log/postgresql \
-p 5432:5432 \
--restart unless-stopped \
postgres:latest \
-c 'config_file=/etc/postgresql/postgresql.conf'
# 修复的验证逻辑
echo "等待容器启动..."
sleep 5
# 1. 首先检查容器是否存在且正在运行
if ! docker ps --filter "name=postgres18" --filter "status=running" | grep -q postgres18; then
echo "❌ 容器未运行或已停止"
echo "容器状态:"
docker ps -a | grep postgres18
echo -e "\n查看日志:"
docker logs postgres18 2>/dev/null || echo "无法获取日志"
exit 1
fi
# 2. 等待数据库服务真正就绪
echo "容器正在运行,等待数据库服务就绪..."
for i in {1..20}; do
if docker exec postgres18 pg_isready -U postgres >/dev/null 2>&1; then
echo "✅ PostgreSQL 18 容器启动成功!"
echo ""
echo "连接信息:"
echo " Host: localhost"
echo " Port: 5432"
echo " User: postgres"
echo " Password: postgres"
echo " Database: postgres"
# 检查日志
echo -e "\n查看容器日志(最后10行):"
docker logs postgres18 --tail 10
# 验证配置
echo -e "\n验证配置:"
docker exec postgres18 psql -U postgres -c "SELECT version();"
echo ""
exit 0
else
echo "等待数据库服务就绪... ($i/20)"
sleep 2
fi
done
# 3. 如果超过时间仍未就绪
echo "❌ 数据库服务未能在预期时间内就绪"
echo "当前容器状态:"
docker ps | grep postgres18
echo -e "\n查看详细日志:"
docker logs postgres18
echo -e "\n尝试手动连接:"
docker exec postgres18 psql -U postgres -c "SELECT 1;" 2>&1 || echo "连接失败"
# 清理选项
echo -e "\n是否清理失败的容器?(y/N): "
read -n 1 CLEANUP
if [[ $CLEANUP == "y" || $CLEANUP == "Y" ]]; then
docker rm -f postgres18 2>/dev/null || true
echo "已清理"
fi
exit 1