关于 db-keys
db-keys 是用于检查主键存在性、类型及其对行标识和索引行为影响的数据库审计技能,帮助开发者发现键设计风险,并区分静态检查与需运行时证据的验证。
主要功能
- 01查找缺少标识符的表或集合
- 02检查 UUID 和整数键策略
- 03标记可变自然键主键
- 04检查复合键列顺序
- 05提供静态及实时验证指引
适用场景
- 01检查架构 DDL 中的主键
- 02依据数据库证据评估键耗尽风险
- 03评估高写入表的键选择
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ hainrixz/ claude-db --skill db-keys安装后在 Claude Code 中输入/db-keys确认已加载。
详细介绍
db-keys (M2)
主键是行的身份契约:它决定行如何被引用、如何在磁盘上聚簇,以及如何扩展。缺少主键或主键即将耗尽,是少数可能拉低评分上限的问题之一。本模块同时涉及两个维度:设计方面的身份建模,以及性能方面的索引局部性和耗尽风险。
检查内容
- 没有主键(或集合中没有唯一的行标识符):这是会触发上限的情况。没有主键的表无法安全地更新、复制或去重。
- 主键类型策略:将随机的
UUIDv4用作聚簇/前导 B-tree 键会导致插入碎片化并使索引膨胀;优先使用按时间排序的UUIDv7/ULID或bigintidentity。对高频插入表上的uuid_generate_v4()默认值发出警示。 - Postgres ≥18(2025 年 9 月正式发布):原生
uuidv7()(RFC 9562)是推荐的按时间排序 UUID 主键默认值(可通过uuid_extract_timestamp()恢复时间戳)。当检测到引擎为 PG ≥18 时,将gen_random_uuid()/v4 默认值视为降级,并建议使用uuidv7()。对于 18 之前的版本或非 Postgres 引擎,gen_random_uuid()和应用侧生成的 UUIDv7 仍然适用。 - 自然键与代理键:将可变的自然键(电子邮件、slug)用作主键,会使每个外键都随之变更;建议使用稳定的代理键。
- 整数位宽耗尽:当表的行数可能超过约 21 亿行时,使用
int4/serial/SERIAL主键——int4耗尽会导致生产环境停止运行。bigint/bigserial是安全的默认选择。 - 复合主键排序:使用复合主键时,前导列应与主要访问/分区模式相匹配(关联到 M9 tenant_id、M11 ESR)。
维度与严重性
- 关系型/宽列存储表没有主键:严重性 5,
fail,维度both,置信度established(限制两个维度的评分上限)。 - 接近耗尽的
int4/serial 主键:仅在有 Tier-1 行数证据时严重性为 5;否则严重性为 4,warn,置信度directional(没有实时数据时绝不触发评分上限)。 - 高频插入表上的
UUIDv4聚簇主键:严重性 3,warn,维度performance,置信度directional。 - 可变自然键主键:严重性 3,
warn,维度design。
Tier-0 静态检查
通过 scripts/parse-schema.mjs 解析 DDL/快照:确认每个表都声明了 PRIMARY KEY(或文档型存储的 _id/分片标识);检查主键列类型是否为 uuid 且默认值是否为 gen_random_uuid()/uuid_generate_v4(),以及是否为 int4/serial。仅解析程序源代码得出的方向性结果,绝不会触发严重性 5 的无主键评分上限。
Tier-1 验证查询
查找没有主键的表:
-- $DATABASE_URL, read-only
SELECT t.table_schema, t.table_name
FROM information_schema.tables t
LEFT JOIN information_schema.table_constraints c
ON c.table_name = t.table_name AND c.table_schema = t.table_schema
AND c.constraint_type = 'PRIMARY KEY'
WHERE t.table_type = 'BASE TABLE' AND t.table_schema NOT IN ('pg_catalog','information_schema')
AND c.constraint_name IS NULL;
检查 int4 主键的剩余空间(确认严重性 5 的耗尽风险):
SELECT max(id) AS cur, 2147483647 AS int4_max, round(100.0*max(id)/2147483647,1) AS pct_used FROM <table>;
发现项
按 schema/finding.schema.json 格式输出。示例:
M2.events.no_primary_key— 基表没有主键(严重性 5,fail,维度both,置信度established)。M2.audit_log.int4_pk_exhaustion—id integer主键的值已接近int4上限的较高百分比(Tier-1 时严重性 5 / 静态检查时严重性 4,维度both)。M2.orders.uuidv4_clustered_pk— 使用gen_random_uuid()默认值的随机uuid主键导致插入碎片化(严重性 3,warn,维度performance,置信度directional)。 每个发现项:evidence.observed引用主键 DDL 或目录查询结果原文;verification.reproduce为上述可运行查询(method: ddl_parse/schema_introspect/query_stat);expected_impact标注影响范围并附带置信度标签。
诚实原则
- 没有 Tier-1 的
max(id)和增长趋势信号时,不要声称int4即将耗尽——静态检查只能给出directional置信度,绝不触发评分上限。 UUIDv4并非“错误”;其代价是高频插入时索引局部性较差。应对影响范围分级,绝不捏造插入吞吐量百分比。- 使用代理键还是自然键取决于具体情境;应说明各自的权衡,不要断言其中一种普遍正确。
评论
支持 Markdown