用 Flyway 管理数据库迁移脚本

This commit is contained in:
Tian jianyong 2025-11-20 16:11:57 +08:00
parent 3ccb2b70ba
commit 7173939776
17 changed files with 672 additions and 510 deletions

View File

@ -178,7 +178,110 @@ docker exec qaup-postgres pg_isready -U qaup
2025-01-10 | v1.0.2→v1.0.3 | 李四 | 程序更新 | 失败 | 配置错误,已回滚
```
## 五、文件说明
## 五、数据库部署和更新策略
### 1. 数据库版本管理
系统使用Flyway进行数据库版本管理所有迁移脚本位于`qaup-admin/src/main/resources/db/migration/`目录下。
**迁移脚本列表**
- `V1.0.0__Initial_baseline.sql` - 基线结构86KB
- `V1.0.1__Initial_data.sql` - 初始数据50KB
- `README.md` - 迁移脚本说明
#### Flyway配置在docker-compose.yml中
```yaml
SPRING_FLYWAY_ENABLED: true # 启用Flyway
SPRING_FLYWAY_BASELINE_ON_MIGRATE: true # 基线迁移(支持已有数据库)
SPRING_FLYWAY_VALIDATE_ON_MIGRATE: true # 验证迁移
SPRING_FLYWAY_CLEAN_DISABLED: true # 禁止清理生产数据库
SPRING_FLYWAY_LOCATIONS: classpath:db/migration # 迁移脚本路径
```
### 2. 数据库部署流程
#### 首次部署(全新环境)
```bash
# 1. 启动基础服务PostgreSQL + Redis
docker compose up -d qaup-postgres qaup-redis
# 2. 等待数据库就绪
sleep 30
# 3. 初始化数据库执行Flyway迁移
# 应用启动时会自动执行Flyway迁移
docker compose up -d qaup-app
# 4. 验证部署
docker compose ps
curl http://localhost:8080/actuator/health
```
#### 已有环境更新
```bash
# Flyway自动处理数据库迁移
# 应用启动时会自动检测并执行需要的迁移
docker compose restart qaup-app
# 检查迁移状态
docker exec qaup-postgres psql -U qaup -d qaup -c "SELECT * FROM flyway_schema_history ORDER BY installed_rank;"
```
### 3. 数据库迁移脚本管理
#### 脚本命名规范
- `V{版本号}__{描述}.sql` - 版本化迁移脚本
- `V1.0.0__Initial_baseline.sql` - 基线结构
- `V1.0.1__Initial_data.sql` - 初始数据
- `V1.0.2__Add_new_feature.sql` - 新功能
#### 迁移类型
1. **结构迁移** - 修改表结构、索引等
2. **数据迁移** - 数据清洗、转换等
3. **函数/存储过程迁移** - 业务逻辑更新
### 4. 数据库维护操作
#### 数据备份和恢复(仅限紧急情况)
```bash
# 备份数据
docker exec qaup-postgres pg_dump -U qaup qaup > backup-$(date +%Y%m%d_%H%M%S).sql
# 恢复数据(生产环境需要谨慎)
cat backup-20250115_143000.sql | docker exec -i qaup-postgres psql -U qaup -d qaup
```
#### 数据库状态监控
```bash
# 查看Flyway迁移状态应用启动日志
docker compose logs qaup-app | grep -i flyway
# 直接查询迁移历史
docker exec qaup-postgres psql -U qaup -d qaup -c "
SELECT version, description, installed_on
FROM flyway_schema_history
ORDER BY installed_rank;"
# 检查应用健康状态
curl http://localhost:8080/actuator/health
```
### 5. 数据库更新最佳实践
#### 开发环境
- 可以使用`flyway.clean()`清理数据库
- 可以使用`flyway.migrate().clean()`重建
#### 生产环境
- 禁止使用`flyway.clean()`
- 优先使用增量迁移脚本
- 重大变更需要测试环境验证
#### 回滚策略
1. **自动化回滚** - 备份恢复
2. **脚本化回滚** - 创建回滚脚本
3. **版本控制** - 通过Flyway版本管理
## 六、文件说明
### 打包环境脚本
- `deploy/package-update.sh` - 生成程序更新包
@ -186,5 +289,10 @@ docker exec qaup-postgres pg_isready -U qaup
### 生产环境脚本
- `deploy-all.sh` - 首次部署/完全重新部署
- `deploy-update.sh` - 程序更新脚本
- `DeployGuide.md` - 本说明文档
- `deploy-update.sh` - 程序更新脚本(自动处理数据库迁移)
- `DeployGuide.md` - 本说明文档
### 数据库脚本目录
- `src/main/resources/db/migration/` - Flyway迁移脚本
- `sql/qaup_database_complete_init.sql` - 完整初始化脚本(参考用途)
- `sql/unified_database_migration.sql` - 合并迁移脚本(历史用途)

View File

@ -1,67 +0,0 @@
#!/bin/bash
# QAUP 数据库初始化脚本
# 直接执行完整的数据库初始化SQL文件
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
echo "=== QAUP 数据库初始化脚本 ==="
echo "版本: 1.0.0"
echo "日期: $(date +%Y-%m-%d %H:%M:%S)"
echo ""
# 检查必要文件是否存在
COMPLETE_INIT_FILE="$SCRIPT_DIR/qaup_database_export.sql"
if [ ! -f "$COMPLETE_INIT_FILE" ]; then
echo "❌ 错误: 未找到完整数据库初始化文件"
echo " 文件路径: $COMPLETE_INIT_FILE"
exit 1
fi
echo "✅ 找到完整数据库初始化文件: $COMPLETE_INIT_FILE"
echo " 文件大小: $(du -sh "$COMPLETE_INIT_FILE" | cut -f1)"
echo ""
# 检查PostgreSQL是否可用
if ! command -v psql &> /dev/null; then
echo "❌ 错误: PostgreSQL客户端(psql)未安装或未在PATH中"
echo " 请确保已安装PostgreSQL并配置环境变量"
exit 1
fi
echo "✅ PostgreSQL客户端已检测到: $(psql --version | head -1)"
echo ""
# 设置默认数据库信息
DEFAULT_DB="qaup"
DEFAULT_USER="qaup"
# 询问用户数据库连接信息
read -p "请输入数据库名称(默认: $DEFAULT_DB: " DB_NAME
DB_NAME=${DB_NAME:-$DEFAULT_DB}
read -p "请输入数据库用户名(默认: $DEFAULT_USER: " DB_USER
DB_USER=${DB_USER:-$DEFAULT_USER}
read -s -p "请输入数据库密码: " DB_PASSWORD
echo ""
# 连接并执行初始化脚本
echo "开始执行数据库初始化..."
echo "========================================="
PGPASSWORD="$DB_PASSWORD" psql -U "$DB_USER" -d "$DB_NAME" -f "$COMPLETE_INIT_FILE" 2>&1 | grep -v "NOTICE"
if [ $? -eq 0 ]; then
echo "========================================="
echo "✅ 数据库初始化成功完成!"
echo " 数据库: $DB_NAME"
echo " 用户: $DB_USER"
else
echo "========================================="
echo "❌ 数据库初始化失败!"
echo " 请检查连接信息和数据库权限"
echo " 确保数据库已经创建: createdb -U $DB_USER $DB_NAME"
exit 1
fi

View File

@ -59,7 +59,7 @@ cp deploy/deploy-update.sh qaup-deploy/
# 复制数据库相关文件
cp deploy/qaup_database_export.sql qaup-deploy/qaup_database_export.sql 2>/dev/null || echo "⚠ 完整初始数据文件不存在"
cp deploy/database-init.sh qaup-deploy/ 2>/dev/null || echo "⚠ 数据库初始化脚本不存在"
# database-init.sh已删除数据库迁移通过Flyway自动化处理
cp deploy/DeployGuide.md qaup-deploy/

View File

@ -1,24 +1,26 @@
# Ubuntu部署指南
> **重要说明**: 本文档描述了现代化的极简部署方案数据库迁移通过Flyway自动化处理无需手动执行SQL脚本。
## 1. 系统环境准备
### Ubuntu系统要求
- **操作系统**: Ubuntu 20.04 LTS 或更高版本
- **内存**: 至少 8GB RAM
- **存储**: 至少 10GB 可用空间
- **存储**: 至少 20GB 可用空间
- **CPU**: 4核或以上
- **网络**: 稳定的互联网连接
- **网络**: 稳定的互联网连接用于下载Docker镜像
### 安装必要软件
```bash
# 系统更新
sudo apt update && sudo apt upgrade -y
# 安装Java 21
# 安装Java 21(用于本地编译)
sudo apt install -y openjdk-21-jdk
java -version # 验证安装
# 安装Maven
# 安装Maven(用于构建)
sudo apt install -y maven
mvn -version # 验证安装
@ -27,269 +29,361 @@ sudo apt install -y docker.io
sudo systemctl start docker
sudo systemctl enable docker
# 安装Docker Compose
sudo apt install -y docker-compose-plugin
# 将当前用户添加到docker组
sudo usermod -aG docker $USER
newgrp docker # 重新加载组权限
# 验证Docker
# 验证安装
docker --version
docker compose version
```
## 2. 获取并编译项目
## 2. 部署方式选择
### 方式一:使用预构建部署包(推荐)
```bash
# 获取项目
# 1. 解压部署包
tar -xzf qaup-deploy.tar.gz
cd qaup-deploy
# 2. 一键部署
./deploy-all.sh
# 3. 检查服务状态
docker compose ps
```
### 方式二:源码编译部署
```bash
# 1. 获取项目源码
git clone <your-repo-url>
cd QAUP-Management
# 编译项目
# 2. 编译项目
mvn clean package -DskipTests
# 验证编译结果
ls -la qaup-admin/target/qaup-admin.jar
```
## 3. 部署方式
### 3.1 Docker Compose部署推荐
```bash
# 创建部署目录
# 3. 创建部署目录
mkdir -p ~/qaup-deploy
cd ~/qaup-deploy
# 复制部署文件
# 4. 复制部署文件
cp /path/to/QAUP-Management/deploy/docker-compose.yml .
cp /path/to/QAUP-Management/deploy/config.yml .
cp /path/to/QAUP-Management/qaup-admin/target/qaup-admin.jar ./app.jar
# 创建数据目录
# 5. 创建数据目录
mkdir -p data/postgres data/redis logs backup
# 启动服务
# 6. 启动服务
docker compose up -d
# 检查服务状态
# 7. 检查服务状态
docker compose ps
```
### 3.2 快速测试部署
### 3.1 部署包内容说明
> **注意**: 仅用于快速测试
```bash
# 创建运行目录
mkdir -p ~/qaup-test
cd ~/qaup-test
# 复制jar文件
cp /path/to/QAUP-Management/qaup-admin/target/qaup-admin.jar ./
# 启动数据库和缓存服务
docker run --name qaup-postgres -e POSTGRES_DB=qaup -e POSTGRES_USER=qaup -e POSTGRES_PASSWORD=qaup123 -p 5432:5432 -d postgis/postgis:17-3.5-alpine
docker run --name qaup-redis -p 6379:6379 -d redis:8.0-alpine
# 等待服务启动
sleep 30
# 运行应用
java -jar qaup-admin.jar --spring.profiles.active=dev
```
qaup-deploy/
├── deploy-all.sh # 一键部署脚本
├── deploy-update.sh # 一键更新脚本
├── docker-compose.yml # Docker编排配置
├── config.yml # 应用配置文件
├── app.jar # 应用JAR文件
└── images.tar.gz # 预拉取的Docker镜像包
```
## 4. 服务管理
### 3.2 现代化特性说明
### 启动/停止/重启
**自动化数据库迁移**: Flyway在应用启动时自动执行数据库迁移
**PostGIS支持**: 内置地理空间数据处理能力
**健康检查**: 自动监控服务状态和依赖关系
**零停机升级**: 只重启应用服务,数据库保持运行
**离线部署**: 预打包镜像,无需互联网连接
## 3. 服务管理
### 3.1 基本服务管理
```bash
# 启动服务
# 进入部署目录
cd ~/qaup-deploy
# 启动所有服务
docker compose up -d
# 停止服务
# 停止所有服务
docker compose down
# 重启应用服务
# 重启应用服务(不影响数据库)
docker compose restart qaup-app
# 查看服务状态
docker compose ps
# 查看日志
# 查看应用日志
docker compose logs -f qaup-app
# 查看数据库日志
docker compose logs qaup-postgres
# 查看Redis日志
docker compose logs qaup-redis
# 查看系统资源使用
docker stats
```
## 5. 访问系统
### 3.2 监控数据库迁移状态
```bash
# 查看Flyway迁移历史
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT * FROM flyway_schema_history ORDER BY installed_rank;"
### 系统地址
# 查看应用日志中的迁移信息
docker compose logs qaup-app | grep -i flyway
# 查看最近的迁移记录
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT version, description, installed_on FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 3;"
```
## 4. 访问系统
### 4.1 系统地址
- **Web管理**: http://<your-server-ip>:8080
- **WebSocket**: ws://<your-server-ip>:8080/collision
- **健康检查**: http://<your-server-ip>:8080/actuator/health
- **API文档**: http://<your-server-ip>:8080/doc.html
### 初始登录
### 4.2 初始登录
- **用户名**: admin
- **密码**: admin123
## 6. 应用更新
### 4.3 快速验证命令
```bash
# 健康检查(验证服务是否正常)
curl http://localhost:8080/actuator/health
### 6.1 基本更新流程
# 检查容器中Java版本
docker exec qaup-app java -version
# 数据库连接测试
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT version();"
# Redis连接测试
docker exec -it qaup-redis redis-cli ping
```
## 5. 应用更新
### 5.1 一键升级(推荐)
使用现代化的升级脚本,支持自动备份、版本检查和回滚:
```bash
# 备份当前版本
# 1. 复制新版本文件并重命名为 new-app.jar
cp /path/to/new/qaup-admin.jar ~/qaup-deploy/new-app.jar
# 2. 进入部署目录
cd ~/qaup-deploy
cp app.jar app.jar.backup.$(date +%Y%m%d_%H%M%S)
# 替换新版本
cp /path/to/new/qaup-admin.jar ./app.jar
# 3. 执行自动升级
./deploy-update.sh
# 重启应用
docker compose restart qaup-app
# 验证更新
curl http://localhost:8080/actuator/health
# 升级过程包括:
# ✅ Java版本兼容性检查
# ✅ 数据库自动备份
# ✅ 应用服务重启
# ✅ Flyway自动迁移
# ✅ 健康检查验证
# ✅ 自动回滚(如需要)
```
### 6.2 Java版本冲突解决
如果遇到 `UnsupportedClassVersionError` 错误表示编译的jar文件与容器中Java版本不匹配
**错误示例**
```
Exception in thread "main" java.lang.UnsupportedClassVersionError:
com/qaup/QuapApplication has been compiled by a more recent version of the Java Runtime
(class file version 65.0), this version of the Java Runtime only recognizes
class file versions up to 61.0
```
**解决方案**
1. **检查Docker镜像配置**
确保 `docker-compose.yml` 中使用Java 21镜像
```yaml
# QAUP 应用服务
qaup-app:
image: m.daocloud.io/docker.io/library/eclipse-temurin:21-jre
```
2. **修改并重新部署**
```bash
# 停止服务
docker compose down
# 备份原文件
cp docker-compose.yml docker-compose.yml.bak
# 修改Java版本如果需要
sed -i 's/eclipse-temurin:17-jre/eclipse-temurin:21-jre/' docker-compose.yml
# 重新启动服务
docker compose up -d
```
3. **验证Java版本**
```bash
# 检查容器中Java版本
docker exec qaup-app java -version
```
### 6.3 完整更新流程
当遇到容器名称冲突或其他问题时,使用完整的更新流程:
### 5.2 手动升级流程
```bash
# 进入部署目录
cd ~/qaup-deploy
# 1. 停止现有服务
docker compose down
# 1. 数据库备份(重要)
docker exec qaup-postgres pg_dump -U qaup qaup > backup/qaup-backup-$(date +%Y%m%d_%H%M%S).sql
# 2. 确认所有容器已停止
docker ps -a | grep qaup
# 3. 如果还有残留容器,强制删除
docker rm -f $(docker ps -aq --filter name=qaup)
# 4. 备份当前jar文件
# 2. 备份当前版本
cp app.jar app.jar.backup.$(date +%Y%m%d_%H%M%S)
# 5. 替换新版本
# 3. 替换新版本
cp /path/to/new/qaup-admin.jar ./app.jar
# 6. 启动新的服务
docker compose up -d
# 4. 重启应用服务(数据库保持运行)
docker compose restart qaup-app
# 7. 检查服务状态
docker compose ps
# 5. 等待启动和迁移完成约2分钟
echo "等待应用启动和数据库迁移..."
sleep 120
# 8. 验证更新
curl -s http://localhost:8080/actuator/health | jq
# 6. 验证升级结果
if curl -f -s http://localhost:8080/actuator/health > /dev/null; then
echo "✅ 升级成功!"
else
echo "❌ 升级失败,开始回滚..."
# 恢复版本
LATEST_BACKUP=$(ls -t app.jar.backup.* 2>/dev/null | head -1)
cp "$LATEST_BACKUP" app.jar
docker compose restart qaup-app
fi
```
### 6.4 故障排除
### 5.3 监控升级过程
#### 6.4.1 容器名称冲突
如果遇到容器名称冲突错误:
```
Error response from daemon: Conflict. The container name "/qaup-app" is already in use
```
解决方法:
```bash
# 方式1完全重建
docker compose down
docker rm -f $(docker ps -aq --filter name=qaup)
docker compose up -d
# 实时查看应用日志包含Flyway迁移信息
docker compose logs -f qaup-app
# 方式2强制重新创建
docker compose up -d --force-recreate
# 检查Flyway迁移状态
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT version, description, installed_on FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 5;"
# 方式3只重新创建特定服务
docker compose up -d --force-recreate qaup-app
# 查看最近的迁移记录
docker compose logs qaup-app | grep -i "flyway.*migrated"
```
#### 6.4.2 Java版本验证
### 5.4 故障排除
确认容器中Java版本与编译版本匹配
#### 5.4.1 Java版本兼容性错误
如果遇到 `UnsupportedClassVersionError`
```
Error: A JNI error has occurred, please check your installation and try again
Error: Could not find or load main class
```
**解决方案**
```bash
# 查看容器Java版本
# 1. 检查容器Java版本
docker exec qaup-app java -version
# 如果需要,检查镜像信息
docker inspect qaup-app | grep -i java
# 2. 验证jar文件编译版本
javap -cp app.jar -version
# 3. 如果版本不匹配,重新编译项目
mvn clean package -DskipTests
# 4. 确认Docker镜像使用Java 21
grep "eclipse-temurin.*21" docker-compose.yml
```
## 7. 数据备份
#### 5.4.2 数据库连接问题
```bash
# 数据库备份
docker exec qaup-postgres pg_dump -U qaup qaup > backup-$(date +%Y%m%d).sql
# 日志轮转保留最近7天
find ~/qaup-deploy/logs -name "*.log" -mtime +7 -delete
```
## 8. 常见问题
### 应用启动失败
```bash
# 查看详细日志
docker compose logs qaup-app
# 检查数据库连接
docker compose logs qaup-postgres
docker exec qaup-postgres pg_isready -U qaup
```
### 端口被占用
```bash
# 检查端口使用情况
netstat -tlnp | grep :8080
# 停止占用端口的进程
sudo kill -9 $(lsof -t -i:8080)
```
### 数据库连接失败
如果迁移失败:
```bash
# 检查数据库服务
docker compose ps
docker exec qaup-postgres pg_isready -U qaup
```
```
## 9. 快速操作指南
### 9.1 开发环境快速部署
```bash
# 克隆项目并编译
git clone <your-repo-url>
cd QAUP-Management
mvn clean package -DskipTests
# 使用部署脚本打包
./deploy/package-all.sh
# 解压并部署
tar -xzf qaup-deploy.tar.gz
cd qaup-deploy
./deploy-all.sh
```
### 9.2 生产环境升级
```bash
cd qaup-deploy
# 复制新版本
cp /path/to/new/qaup-admin.jar ./new-app.jar
# 执行自动升级
./deploy-update.sh
# 验证升级结果
curl http://localhost:8080/actuator/health
```
### 9.3 日常运维检查
```bash
cd qaup-deploy
# 检查服务状态
docker compose ps
# 查看最近日志
docker compose logs --tail=50 qaup-app
# 检查数据库迁移状态
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT version, description, installed_on FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 3;"
# 系统健康检查
curl -s http://localhost:8080/actuator/health | jq
```
### 9.4 缓存优化
```bash
# 监控Redis内存使用
docker exec -it qaup-redis redis-cli INFO memory
# 清理过期缓存
docker exec -it qaup-redis redis-cli FLUSHDB
```
## 10. 现代化部署优势
### 10.1 核心特性
**极简操作**: 解压 → 运行脚本2步完成部署
**自动迁移**: Flyway处理数据库版本管理无需手动SQL
**零停机升级**: 只重启应用服务,数据库持续运行
**PostGIS支持**: 内置地理空间数据处理能力
**健康监控**: 自动化服务依赖检查和状态监控
**离线部署**: 预打包Docker镜像无需互联网
**一键回滚**: 升级失败自动回滚到上一版本
**版本兼容**: Java 21运行时确保版本一致性
### 10.2 与传统方案对比
| 特性 | 传统方案 | 现代化方案 |
|------|----------|------------|
| 部署步骤 | 手动配置SQL、修改配置、重启服务 | 解压脚本、自动迁移、一键完成 |
| 数据库迁移 | 手动执行SQL脚本易出错 | Flyway自动版本管理 |
| 停机时间 | 需要停机维护 | 零停机升级 |
| 回滚复杂度 | 手动恢复数据库和配置 | 自动回滚机制 |
| 环境一致性 | 容易出现环境差异 | 容器化确保一致性 |
| 地理空间 | 需要额外安装PostGIS | 内置PostGIS支持 |
### 10.3 技术架构
- **运行时**: Java 21 + Spring Boot 3
- **数据库**: PostgreSQL 17 + PostGIS 3.5
- **缓存**: Redis 8
- **容器化**: Docker + Docker Compose
- **迁移工具**: Flyway自动化版本管理
- **监控**: Spring Boot Actuator + 健康检查
---
## 支持和帮助
如遇到问题,请检查:
1. 系统要求和依赖软件版本
2. Docker和Docker Compose安装状态
3. 网络连接和防火墙配置
4. 磁盘空间和文件权限
5. 应用日志和数据库日志
更多详细信息请参考:
- [deploy-design.md](./deploy-design.md) - 完整部署设计文档
- [environment.md](./environment.md) - 环境配置指南
- [ADXP_WebSocket.md](./ADXP_WebSocket.md) - WebSocket服务说明

View File

@ -1,142 +0,0 @@
# PostgreSQL 数据库迁移指南
## 概述
本文档描述如何将本地 PostgreSQL 数据库完全覆盖导入到远程服务器。
**场景:**
- 本地数据库用户postgres
- 远程数据库用户qaup
- 数据库名称qaup
- 操作方式:完全覆盖
## 第一步:本地数据库导出
### 导出完整数据库
```bash
# 导出数据库(包含结构和数据,处理用户名差异)
pg_dump -h localhost -U postgres -d qaup --no-owner --no-privileges --clean --if-exists -f qaup_database_export.sql
```
**参数说明:**
- `--no-owner`: 不包含对象所有者信息,避免用户名冲突
- `--no-privileges`: 不包含权限设置,导入后重新设置权限
- `--clean --if-exists`: 清理现有对象(如果存在)
- `-f`: 指定输出文件名
## 第二步:远程服务器完全覆盖
```bash
# 1. 删除现有数据库
psql -U qaup -d postgres -c "DROP DATABASE IF EXISTS qaup;"
# 2. 重新创建数据库
psql -U qaup -d postgres -c "CREATE DATABASE qaup OWNER qaup;"
# 3. 设置PostGIS扩展
psql -U qaup -d qaup -c "CREATE EXTENSION IF NOT EXISTS postgis;"
# 4. 导入数据
psql -U qaup -d qaup -f qaup_database_export.sql
```
## 第三步:验证导入结果
### 检查数据库结构
```bash
# 查看所有表
psql -U qaup -d qaup -c "\dt"
# 查看特定表结构
psql -U qaup -d qaup -c "\d traffic_lights"
```
### 验证数据完整性
```bash
# 检查关键表的数据量
psql -U qaup -d qaup -c "SELECT count(*) FROM traffic_lights;"
psql -U qaup -d qaup -c "SELECT count(*) FROM intersections;"
psql -U qaup -d qaup -c "SELECT count(*) FROM sys_vehicle_info;"
```
### 检查用户权限
```bash
# 确保qaup用户拥有所有表的权限
psql -U qaup -d qaup -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO qaup;"
psql -U qaup -d qaup -c "GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO qaup;"
```
## 注意事项
1. **备份重要性**:操作前确保远程数据库已备份(如有重要数据)
2. **网络连接**:确保网络稳定,大数据库传输可能需要较长时间
3. **磁盘空间**:确认远程服务器有足够存储空间
4. **权限检查**确保qaup用户有CREATE DATABASE权限方案A
5. **应用停机**:建议在应用停机时间窗口执行,避免数据不一致
## 故障排除
### 连接失败
```bash
# 检查用户权限
psql -U qaup -d postgres -c "SELECT current_user;"
```
### 导入错误
```bash
# 查看详细错误信息
psql -U qaup -d qaup -f qaup_database_export.sql 2>&1 | tee import.log
```
### 权限问题
```bash
# 重置所有权限
psql -U qaup -d qaup -c "
GRANT ALL PRIVILEGES ON DATABASE qaup TO qaup;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO qaup;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO qaup;
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO qaup;
"
```
## 完成后清理
```bash
# 删除本地导出文件(可选)
rm qaup_database_export.sql
# 删除临时脚本如果使用了方案B
rm drop_tables.sql
```
## Java版本兼容性注意事项
如果在执行数据库迁移后更新应用需要注意Java版本兼容性
### 版本匹配检查
- **编译版本**: 确保应用jar文件在Java 21环境下编译
- **运行版本**: Docker容器中运行Java 21
### 版本不匹配错误示例
如果遇到 `UnsupportedClassVersionError` 错误:
```
class file has been compiled by a more recent version of the Java Runtime
(class file version 65.0), this version of the Java Runtime only recognizes
class file versions up to 61.0
```
### 解决方案
1. 确认Docker镜像使用Java 21
```yaml
image: eclipse-temurin:21-jre
```
2. 检查容器Java版本
```bash
docker exec <container-name> java -version
```
---
**创建时间:** 2025-09-25
**适用版本:** PostgreSQL 12+
**测试环境:** QAUP-Management 1.0.1

View File

@ -1,5 +1,5 @@
# QAUP 极简离线部署方案
Spring Boot + Redis + PostgreSQL一键部署、一键升级
Spring Boot + Redis + PostgreSQL with PostGIS(一键部署、一键升级)
## 1. 设计原则
@ -7,80 +7,139 @@ Spring Boot + Redis + PostgreSQL一键部署、一键升级
- **离线部署**:预打包所有依赖,无需联网
- **一键操作**:部署和升级都是一条命令
- **配置灵活**:关键配置可外部修改
- **自动化迁移**数据库版本自动管理Flyway
## 2. 打包准备(开发环境执行一次)
### 2.1 打包脚本package.sh
### 2.1 打包脚本package-all.sh
```bash
#!/bin/bash
echo "=== QAUP 打包脚本 ==="
# 1. 构建应用
# 1. 构建应用在macOS上
mvn clean package -DskipTests
# 2. 拉取并导出镜像
docker pull openjdk:21-jre-alpine
docker pull redis:8-alpine
docker pull postgres:17-3.5-alpine
docker save openjdk:21-jre-alpine redis:8-alpine postgres:17-3.5-alpine | gzip > images.tar.gz
# 2. 拉取并导出镜像(在服务器上)
docker pull m.daocloud.io/docker.io/postgis/postgis:17-3.5-alpine
docker pull m.daocloud.io/docker.io/library/redis:8.0-alpine
docker pull m.daocloud.io/docker.io/library/eclipse-temurin:21-jre
# 导出镜像
docker save m.daocloud.io/docker.io/postgis/postgis:17-3.5-alpine \
m.daocloud.io/docker.io/library/redis:8.0-alpine \
m.daocloud.io/docker.io/library/eclipse-temurin:21-jre | gzip > images.tar.gz
# 3. 准备部署包
mkdir -p qaup-deploy
cp qaup-admin/target/qaup-admin.jar qaup-deploy/app.jar
cp deploy/simple/* qaup-deploy/
cp deploy/docker-compose.yml qaup-deploy/
cp deploy/config.yml qaup-deploy/
cp images.tar.gz qaup-deploy/
# 4. 打包
cd qaup-deploy && zip -r ../qaup-deploy-$(date +%Y%m%d).zip .
echo "打包完成: qaup-deploy-$(date +%Y%m%d).zip"
tar -czf qaup-deploy-$(date +%Y%m%d-%H%M%S).tar.gz -C qaup-deploy .
echo "打包完成: qaup-deploy-$(date +%Y%m%d-%H%M%S).tar.gz"
```
### 2.2 部署包结构(极简版)
### 2.2 部署包结构
```
qaup-deploy.zip
├── images.tar.gz # Docker镜像包
├── docker-compose.yml # 服务编排
├── app.jar # 应用程序
├── config.yml # 外部配置(可修改)
├── init.sql # 数据库初始化脚本
├── deploy.sh # 一键部署
└── update.sh # 一键升级
qaup-deploy.tar.gz
├── images.tar.gz # Docker镜像包PostGIS + Redis + Java21
├── docker-compose.yml # 服务编排(包含健康检查)
├── app.jar # 应用程序
├── config.yml # 外部配置(可修改)
├── deploy-all.sh # 一键部署脚本
├── deploy-update.sh # 一键升级脚本
├── DeployGuide.md # 详细部署指南
└── qaup_database_export.sql # 完整数据库备份(可选)
```
## 3. docker-compose.yml极简版
## 3. docker-compose.yml当前实际版本
```yaml
services:
app:
image: openjdk:21-jre-alpine
container_name: qaup-app
restart: always
ports:
- "8080:8080"
volumes:
- ./app.jar:/app.jar
- ./config.yml:/config.yml
command: ["java", "-jar", "/app.jar", "--spring.config.location=/config.yml"]
depends_on:
- db
- redis
redis:
image: redis:8-alpine
container_name: qaup-redis
restart: always
command: ["redis-server", "--maxmemory", "256mb", "--maxmemory-policy", "allkeys-lru"]
db:
image: postgres:17-3.5-alpine
container_name: qaup-db
restart: always
# PostgreSQL + PostGIS 数据库服务
qaup-postgres:
image: m.daocloud.io/docker.io/postgis/postgis:17-3.5-alpine
container_name: qaup-postgres
restart: unless-stopped
environment:
POSTGRES_DB: qaup
POSTGRES_USER: qaup
POSTGRES_PASSWORD: qaup123
volumes:
- ./data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
- ./data/postgres:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U qaup"]
interval: 30s
timeout: 10s
retries: 3
# Redis 缓存服务
qaup-redis:
image: m.daocloud.io/docker.io/library/redis:8.0-alpine
container_name: qaup-redis
restart: unless-stopped
command: ["redis-server", "--maxmemory", "256mb", "--maxmemory-policy", "allkeys-lru"]
volumes:
- ./data/redis:/data
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
# QAUP 应用服务Java 21
qaup-app:
image: m.daocloud.io/docker.io/library/eclipse-temurin:21-jre
container_name: qaup-app
restart: unless-stopped
environment:
SPRING_PROFILES_ACTIVE: prod
LOG_PATH: /app/logs
# 数据库连接配置
DB_HOST: qaup-postgres
DB_PORT: 5432
DB_NAME: qaup
DB_USER: qaup
DB_PASSWORD: qaup123
# Flyway配置自动化数据库迁移
SPRING_FLYWAY_ENABLED: true
SPRING_FLYWAY_BASELINE_ON_MIGRATE: true
SPRING_FLYWAY_VALIDATE_ON_MIGRATE: true
SPRING_FLYWAY_CLEAN_DISABLED: true
volumes:
- ./app.jar:/app/app.jar
- ./config.yml:/app/config.yml
- ./logs:/app/logs
- ./backup:/app/backup
ports:
- "8080:8080"
depends_on:
qaup-postgres:
condition: service_healthy
qaup-redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 5
start_period: 120s
command: [
"sh", "-c",
"echo 'Waiting for database to be ready...' &&
sleep 10 &&
echo 'Starting QAUP application with Flyway migration...' &&
java -jar /app/app.jar --spring.config.location=/app/config.yml"
]
networks:
default:
name: qaup-network
```
## 4. 外部配置文件config.yml
@ -89,21 +148,6 @@ services:
server:
port: 8080
# 数据库配置
spring:
datasource:
url: jdbc:postgresql://qaup-db:5432/qaup
username: qaup
password: qaup123
driver-class-name: org.postgresql.Driver
# Redis配置
data:
redis:
host: qaup-redis
port: 6379
database: 0
# 应用配置
qaup:
# 文件上传路径
@ -113,64 +157,95 @@ qaup:
api-host: 192.168.1.100
api-port: 8090
# 日志配置(简化)
# 日志配置
logging:
level:
com.qaup: info
com.qaup: INFO
pattern:
console: "%d{HH:mm:ss} %-5level %logger{36} - %msg%n"
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file:
name: /app/logs/qaup.log
# 注意数据库和Redis配置通过环境变量设置
```
## 5. 数据库初始化init.sql
```sql
-- 创建基础表结构
CREATE TABLE IF NOT EXISTS sys_user (
user_id SERIAL PRIMARY KEY,
user_name VARCHAR(30) NOT NULL,
nick_name VARCHAR(30) NOT NULL,
password VARCHAR(100) DEFAULT '',
status CHAR(1) DEFAULT '0',
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
## 5. 自动化数据库迁移Flyway
-- 插入默认管理员
INSERT INTO sys_user (user_name, nick_name, password)
VALUES ('admin', '管理员', '$2a$10$7JB720yubVSOfvam/RtmyO4wV/hOoLsKpHpJI.VqSb/VXaVzqQqhu')
ON CONFLICT DO NOTHING;
-- 其他标准数据...
### 5.1 迁移脚本位置
```
qaup-admin/src/main/resources/db/migration/
├── V1.0.0__Initial_baseline.sql # 数据库基线结构86KB
├── V1.0.1__Initial_data.sql # 初始数据50KB
└── README.md # 迁移脚本编写规范
```
## 6. 一键部署deploy.sh
### 5.2 自动迁移机制
- **应用启动时自动执行**无需手动运行SQL脚本
- **版本控制**:所有迁移按版本顺序执行
- **幂等性**:安全重复执行,不会重复创建对象
- **健康检查**:依赖数据库健康状态启动应用
### 5.3 迁移状态查询
```bash
# 查看应用日志中的迁移信息
docker compose logs qaup-app | grep -i flyway
# 直接查询数据库
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT * FROM flyway_schema_history ORDER BY installed_rank;"
```
## 6. 一键部署deploy-all.sh
```bash
#!/bin/bash
echo "=== QAUP 一键部署 ==="
# 检查Docker
if ! command -v docker &> /dev/null; then
echo "❌ Docker 未安装"
exit 1
fi
# 载入镜像
echo "载入Docker镜像..."
docker load -i images.tar.gz
# 创建数据目录
mkdir -p data
echo "创建数据目录..."
mkdir -p data/postgres data/redis logs
# 启动服务
echo "启动服务..."
docker compose up -d
# 等待启动
echo "等待服务启动(30秒..."
sleep 30
# 等待服务启动
echo "等待服务启动(60秒..."
sleep 60
echo "✅ 部署完成!访问: http://localhost:8080"
echo "默认账号: admin / admin123"
# 检查服务状态
if curl -f -s http://localhost:8080/actuator/health > /dev/null 2>&1; then
echo "✅ 部署成功!"
echo ""
echo "访问地址: http://localhost:8080"
echo "数据库: localhost:5432 (qaup/qaup123)"
echo "Redis: localhost:6379"
echo ""
echo "管理命令:"
echo " 查看状态: docker compose ps"
echo " 查看日志: docker compose logs -f qaup-app"
echo " 停止服务: docker compose down"
echo " 升级应用: ./deploy-update.sh"
else
echo "❌ 服务启动失败,请检查日志:"
docker compose logs
fi
```
## 7. 客户部署1条命令
```bash
unzip qaup-deploy.zip && cd qaup-deploy && ./deploy.sh
tar -xzf qaup-deploy.tar.gz && cd qaup-deploy && ./deploy-all.sh
```
## 8. 一键升级update.sh
## 8. 一键升级(deploy-update.sh
```bash
#!/bin/bash
echo "=== QAUP 一键升级 ==="
@ -186,86 +261,180 @@ echo "验证Java版本兼容性..."
if command -v java &> /dev/null; then
LOCAL_JAVA_VERSION=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed 's/[^0-9.]*\([0-9.]*\).*/\1/')
echo "本地Java版本: $LOCAL_JAVA_VERSION"
echo "容器Java版本: eclipse-temurin:21-jre"
fi
# 备份当前版本
cp app.jar app.jar.backup
echo "已备份当前版本"
echo "备份当前版本..."
cp app.jar app.jar.backup.$(date +%Y%m%d_%H%M%S)
# 停止应用
# 数据库备份(重要)
echo "备份数据库..."
docker exec qaup-postgres pg_dump -U qaup qaup > backup/qaup-backup-$(date +%Y%m%d_%H%M%S).sql
# 停止应用(不影响数据库)
echo "停止应用服务..."
docker compose stop app
docker compose stop qaup-app
# 替换应用
cp new-app.jar app.jar
echo "已更新应用文件"
# 启动应用
# 启动应用Flyway自动处理数据库迁移
echo "启动应用服务..."
docker compose start app
docker compose start qaup-app
# 等待启动
echo "等待服务启动30秒..."
sleep 30
# 等待启动和迁移完成
echo "等待应用启动和数据库迁移120秒..."
sleep 120
echo "✅ 升级完成!"
echo "如有问题,可执行回滚: cp app.jar.backup app.jar && docker compose restart app"
# 检查升级结果
if curl -f -s http://localhost:8080/actuator/health > /dev/null 2>&1; then
echo "✅ 升级成功!"
echo ""
echo "Flyway迁移状态:"
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT version, description, installed_rank FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 5;"
else
echo "❌ 升级失败,开始回滚..."
# 恢复jar文件
LATEST_BACKUP=$(ls -t app.jar.backup.* 2>/dev/null | head -1)
if [ -n "$LATEST_BACKUP" ]; then
cp "$LATEST_BACKUP" app.jar
docker compose restart qaup-app
echo "✅ 已回滚到版本: $LATEST_BACKUP"
else
echo "❌ 未找到备份文件,请手动处理"
fi
fi
```
## 9. Java版本兼容性注意事项
### 9.1 编译与运行环境匹配
- **编译环境**: 确保项目在Java 21环境下编译
- **运行环境**: Docker镜像必须与编译版本匹配`openjdk:21-jre-alpine` 或 `eclipse-temurin:21-jre`
- **运行环境**: Docker镜像使用 `eclipse-temurin:21-jre`
### 9.2 常见版本错误
如果遇到 `UnsupportedClassVersionError`,确认以下配置:
```yaml
# docker-compose.yml 中必须使用Java 21镜像
services:
app:
# 错误示例(可能导致版本不匹配)
# image: openjdk:17-jre-alpine
qaup-app:
# 正确示例
image: openjdk:21-jre-alpine
image: m.daocloud.io/docker.io/library/eclipse-temurin:21-jre
```
### 9.3 版本验证命令
```bash
# 检查容器中Java版本
docker exec <container-name> java -version
docker exec qaup-app java -version
# 检查jar文件编译版本
javap -cp <jar-file> -version <main-class>
javap -cp app.jar -version
# 快速健康检查
curl http://localhost:8080/actuator/health
```
## 9. 操作总结
## 10. 系统维护操作
### 10.1 日常运维命令
```bash
# 查看服务状态
docker compose ps
# 查看应用日志
docker compose logs -f qaup-app
# 查看数据库日志
docker compose logs qaup-postgres
# 查看Redis日志
docker compose logs qaup-redis
# 查看系统资源使用
docker stats
# 数据库连接测试
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT version();"
# Redis连接测试
docker exec -it qaup-redis redis-cli ping
```
### 10.2 监控数据库迁移状态
```bash
# 查看Flyway迁移历史
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT * FROM flyway_schema_history ORDER BY installed_rank;"
# 查看应用日志中的迁移信息
docker compose logs qaup-app | grep -i flyway
# 查看最近的迁移记录
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT version, description, installed_on FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 3;"
```
### 10.3 数据备份和恢复
```bash
# 手动备份数据库
docker exec qaup-postgres pg_dump -U qaup qaup > backup/manual-backup-$(date +%Y%m%d_%H%M%S).sql
# 恢复数据库(需要停止应用)
docker compose stop qaup-app
docker exec -i qaup-postgres psql -U qaup qaup < backup/qaup-backup-20250120_143000.sql
docker compose start qaup-app
```
### 10.4 完全重置(开发测试用)
```bash
# 停止所有服务
docker compose down
# 删除数据目录(⚠️ 注意:这会删除所有数据)
rm -rf data/
# 重新部署
./deploy-all.sh
```
## 11. 操作总结
### 开发环境(一次性)
```bash
./package.sh # 打包部署文件
# 在macOS上构建
mvn clean package -DskipTests
./deploy/package-all.sh
# 或在服务器上打包
./deploy/package-all.sh
```
### 客户环境
```bash
# 首次部署
unzip qaup-deploy.zip && cd qaup-deploy && ./deploy.sh
tar -xzf qaup-deploy.tar.gz && cd qaup-deploy && ./deploy-all.sh
# 日常升级
./update.sh
# 程序更新
# 1. 复制新jar文件并重命名为 new-app.jar
# 2. 执行更新
./deploy-update.sh
# 查看状态
docker compose ps
# 查看日志
docker compose logs -f app
docker compose logs -f qaup-app
```
## 10. 优势总结
## 12. 现代化优势总结
**极简部署**:解压 → 运行脚本2步完成
**极简升级**替换jar → 运行脚本,自动完成
**离线友好**:所有依赖预打包,无需联网
**配置灵活**:关键配置外部文件,可随时修改
**自动初始化**:数据库结构和标准数据自动创建
**一键回滚**:升级失败可快速回滚到上一版本
**自动化迁移**Flyway自动处理数据库版本管理
**健康检查**:服务依赖和健康状态监控
**PostGIS支持**:内置地理空间数据库能力
**一键回滚**:升级失败可快速回滚到上一版本
**零停机升级**:只重启应用服务,数据库保持运行
**版本兼容**Java 21运行时确保版本一致性