fe28ddeaacdce5786089e4449ab7bb8d162dda5a
- compare usercert_tab by subject raw bytes + certtype - generate single annotated CSV report - generate merge-<timestamp>.sql in current directory for DBA execution - preserve GBK DN bytes via ATTACH + INSERT OR REPLACE / UPDATE - compatible with sqlite3 3.6.20 and JDK 1.8
HSM 主备数据库证书比对工具
Java 8 命令行工具,用于比对 HSM 主库、从库 SQLite 数据库中的 usercert_tab,生成一份差异报表,并按人工标注的“合并选择”生成在主库执行的批量 SQL 脚本。
- 身份键:
subject原始字节 +certtype - 三类差异:主库多、从库多、不一致
- 报表:单份 CSV(UTF-8 + BOM),含“合并选择”列
- 合并方式:生成
merge-<时间戳>.sql,由 DBA 在主库执行 - 工具本身只读源库,不直接修改任何数据库
- 脚本通过
ATTACH从从库按原始字节复制,DN 中文(GBK 字节)不经过 Java 字符串 - 不生成日志文件,信息只输出到控制台
详细需求与设计见 需求文档.md、设计文档.md。
构建
要求:JDK 8 + Maven 3.x。
mvn clean package
# 产物:target/cert-compare.jar(fat jar,含 sqlite-jdbc 原生库)
当前构建:12 个单元测试全部通过,jar 约 9.8 MB。
配置
config.properties(UTF-8):
db.main=/app/cert-compare/main.db
db.slave=/app/cert-compare/slave.db
db.text.encoding=GB18030
dn.match=EXACT
sn.normalize=HEX
report.dir=/app/cert-compare/reports
report.csv.bom=true
相对路径以配置文件所在目录为基准。SQL 脚本不配置输出目录,直接写入运行时当前目录。
使用
交互模式
java -Dfile.encoding=UTF-8 -jar cert-compare.jar --config config.properties
cert-compare> set main /app/cert-compare/main.db
cert-compare> set slave /app/cert-compare/slave.db
cert-compare> compare
cert-compare> sql --report /app/cert-compare/reports/compare-report-20261104-213307-annotated.csv
一次性命令
# 1. 生成报表
java -Dfile.encoding=UTF-8 -jar cert-compare.jar compare --config config.properties
# 2. 人工标注“合并选择”后生成批量 SQL
java -Dfile.encoding=UTF-8 -jar cert-compare.jar sql \
--config config.properties \
--report /app/cert-compare/reports/compare-report-20261104-213307-annotated.csv
# 3. 由 DBA 备份主库后执行脚本
cp -p /app/cert-compare/main.db /app/cert-compare/main.db.bak-$(date +%Y%m%d-%H%M%S)
sqlite3 /app/cert-compare/main.db < /app/cert-compare/merge-20261104-213307.sql
sql 只生成脚本,不写数据库、不需要确认参数;脚本直接写入运行时的当前目录。
合并选择规则
| 类型 | 默认值 | 允许值 |
|---|---|---|
| 主库多 | 主 | 仅主 |
| 从库多 | 备 | 仅备 |
| 不一致 | 空 | 主 / 备 |
sql 生成前会重新比对并校验报表是否过期、标注是否完整;不合法时拒绝生成脚本并提示行号(退出码 5)。
报表
文件名:compare-report-yyyyMMdd-HHmmss.csv。
列为:序号,类型,DN,DN_HEX,CN,CERTTYPE,主库SN,从库SN,主库生效,主库失效,从库生效,从库失效,主库状态,从库状态,差异字段,合并选择。
合并选择放在最后一列,方便直接填写“主”或“备”。- 报表不含“备注”列;日期非法、SN/DN 为空等异常在
compare控制台“提示”中输出。 DN_HEX带HEX:前缀,避免 Excel 把长十六进制转为科学计数法。- 报表可用 Excel 直接编辑,另存为 UTF-8 CSV 或 GBK CSV 均可读取。
sql只信任“合并选择”列,证书数据始终取自当前数据库。
生成的 SQL 脚本
- 文件名:
merge-yyyyMMdd-HHmmss.sql,写入运行时当前目录,不覆盖历史脚本。 ATTACH DATABASE '<从库>' AS cert_src,按hex(subject)+certtype定位。- 从库多、不一致选备:
INSERT OR REPLACE ... SELECT(整行复制)。 dn.match=TRIM且主备 DN 字节不同时:UPDATE ... SET col = (SELECT ...),按主库字节定位。- 主库多、不一致选主:不产生语句。
- 使用
BEGIN IMMEDIATE/COMMIT包裹,可重复执行(幂等)。 - 末尾输出
SELECT 'rows'与PRAGMA integrity_check供执行后自检。 - 脚本为 UTF-8 无 BOM,SQL 与字符串字面量全 ASCII,DN 只以十六进制出现。
- 兼容服务器 sqlite3 3.6.20。
测试数据
scripts/test-data-main.sql 与 scripts/test-data-slave.sql 会在原测试库中增加 3 组“不一致”数据:
| DN | CERTTYPE | 差异 | 主库 | 从库 |
|---|---|---|---|---|
CN=diff-sn-01 |
0 | SN | 0A0B0C01 |
0A0B0C11 |
CN=diff-time-02 |
2 | 失效时间 | 20301231235959 |
20311231235959 |
CN=diff-stat-03 |
5 | 状态 | 0 |
1 |
执行前请备份:
cp -p main.db main.db.bak-$(date +%Y%m%d-%H%M%S)
cp -p slave.db slave.db.bak-$(date +%Y%m%d-%H%M%S)
sqlite3 main.db < scripts/test-data-main.sql
sqlite3 slave.db < scripts/test-data-slave.sql
当前测试库预期结果:
主库 4 条,从库 15 条
一致 0、主库多 1、从库多 12、不一致 3
报表 16 条
执行脚本后主库 16 条(2 条选主、1 条选备)
部署
scp target/cert-compare.jar root@172.1.41.139:/app/cert-compare/
scp config.properties root@172.1.41.139:/app/cert-compare/
scp scripts/cert-compare.sh root@172.1.41.139:/app/cert-compare/
ssh root@172.1.41.139
cd /app/cert-compare
chmod +x cert-compare.sh
./cert-compare.sh
cert-compare.sh 已设置 -Dfile.encoding=UTF-8 -Xmx256m。
退出码
| 码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | 未预期内部错误 |
| 2 | 参数/配置错误 |
| 4 | 数据库/结构/完整性错误 |
| 5 | 报表过期、标注非法、SQL 脚本生成/写入失败 |
Languages
Java
99.9%
Shell
0.1%