关于 atlas-postgres
这是面向 Atlas PostgreSQL 模式管理的专项技能,供处理数据库结构与迁移的 Agent 使用。内容补充通用 Atlas 工作流之外的 PostgreSQL 规则、边缘情况和测试指引。
主要功能
- 01PostgreSQL 模式范围与开发数据库指南
- 02安全、角色和权限指南
- 03HCL 模式与对象参考
- 04迁移安全和 lint 指南
- 05模式、迁移及自定义规则测试
适用场景
- 01为 PostgreSQL 模式对象选择 URL 范围
- 02规划安全的索引和约束变更
- 03排查 PostgreSQL 特有的迁移错误
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ ariga/ atlas --skill atlas-postgres安装后在 Claude Code 中输入/atlas-postgres确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlreferences/custom-rules.mddev-database.mdhcl.mdmigrations.mdobjects.mdsecurity.mdtesting.md详细介绍
Atlas for PostgreSQL
Atlas 管理架构时,PostgreSQL 有哪些特定之处。atlas 技能涵盖工作流和命令;本技能涵盖 PostgreSQL 特有的规则、边缘情况和解答。兼容 PostgreSQL 的引擎(如 CockroachDB、YugabyteDB 和 Aurora DSQL)在某些方面的行为有所不同:请参阅它们的指南(https://atlasgo.io/databases)。
文件
本技能由 SKILL.md 和 references/ 下的七个参考文件组成,每个文件均可通过
https://atlasgo.io/skills/atlas-postgres/references/<name> 获取。任务需要时,请阅读相应参考文件:
| 文件 | 适用内容 |
|---|---|
references/dev-database.md | 开发数据库 URL 及其用途范围、atlas tool docker、docker 块和 baseline、扩展、RDS、Cloud SQL、Supabase、Neon、Azure、连接 URL |
references/security.md | 角色和用户、GRANT 和 REVOKE、ALTER DEFAULT PRIVILEGES、所有权、行级安全、云服务提供商的管理员角色 |
references/objects.md | 序列、serial 和 identity 列、枚举、域、列类型变更、函数、触发器、视图、分区、索引、Atlas 不管理的对象 |
references/hcl.md | 用 HCL 编写架构:NOT NULL 默认值、列类型和 sql()、默认值、引用、键、索引、表设置、函数体、种子数据、输入变量 |
references/migrations.md | 锁和并发索引、PG* lint 检查结果、事务、连接池、锁安全的 NOT NULL、种子数据 |
references/custom-rules.md | 当没有分析器能覆盖某项检查时,如何用 HCL 规则语言编写自定义 lint 规则:谓词、运算符、各 PostgreSQL 对象公开的内容、示例 |
references/testing.md | 测试每项变更:针对函数、触发器、视图、域和策略的架构测试、包含预置行的迁移测试、行级安全测试、模板数据库、pgTAP |
依赖
atlas 技能,需安装在本技能旁边(../atlas/SKILL.md)。如果缺少该文件,请将
https://atlasgo.io/skills/atlas/SKILL.md 下载到 ../atlas/SKILL.md,并将其“文件”部分中列出的各个参考文件下载到
../atlas/references/<name>。
规则
- 首先使用
atlas whoami检查登录状态。如果显示未登录,请让用户运行atlas login: 未登录时,Atlas 会遗漏 PostgreSQL 架构中的大多数内容。检查会静默跳过视图、函数、 触发器、序列、扩展、分区和策略;如果目标状态定义了这些对象,则会报错,错误中包含are available to logged-in users only。没有账户的用户可以通过atlas login开始免费试用。 - 根据架构包含的对象选择 URL 范围:
- 架构范围:URL 中带有
search_path。Atlas 管理该架构,并写入不带限定符的语句 (users)。数据库范围:URL 中没有search_path。Atlas 覆盖所有架构,并为每条语句添加限定符 (public.users)。 - 数据库级对象不属于任何架构:扩展、事件触发器和外部服务器。架构范围的 URL 无法看到它们, 也不会在计划中包含它们,且不会报错;因此,声明了这些对象的架构必须使用数据库范围。
- 架构级对象在任一范围下均可使用:表及其索引、约束、触发器和策略,以及视图、函数、过程、 序列和类型。
- 角色和用户属于集群级对象,由实例中的所有数据库共享。管理它们需要使用数据库范围 (规则 5)。
- 开发数据库 URL 必须与目标采用相同的范围。在架构范围下,Docker 开发数据库 URL 使用
search_path=public;该架构存在于每个新建数据库中,无论目标指定了哪个架构。你提供的 开发数据库可以使用任何空架构。
- 架构范围:URL 中带有
- 开发数据库使用与目标相同的主版本和扩展:
docker://postgres/<version>/dev。对于架构使用但不由其管理的内容, 例如扩展、服务提供商角色或其他团队的架构,应在docker块的baseline中创建。切勿将dev指向真实环境的数据库。 - 目标状态中的
ALTER DEFAULT PRIVILEGES永远不会出现在迁移中:Atlas 会在开发数据库上执行它, 并为其涵盖的每个对象规划一条 GRANT。将它放在这些对象之前,且不要使用FOR ROLE。 - 管理角色需要使用数据库范围和
mode { roles = true }。将 Atlas 不得更改的每个角色标记为external = true,并在开发数据库的baseline中创建授权语句引用的外部角色。在托管服务上, 排除服务提供商的管理员角色 (references/security.md,托管服务提供商)。 - 在有数据的表上并发创建和删除索引:使用
concurrent_index差异策略,或编写以-- atlas:txmode none开头的文件。迁移文件中绝不要写BEGIN或COMMIT:除非设置txmode none,否则 Atlas 会在事务中运行每个文件。 - 先将
CHECK约束和外键添加为NOT VALID,再在单独的事务中验证它们:使用txmode none文件,或后续文件。在大表上使用不会引发锁问题的NOT NULL策略。 - 通过直接连接应用迁移,绝不要通过事务模式的连接池代理连接,例如 Supabase 的事务连接池
(端口 6543)、Neon 的
-pooler端点,或事务模式下的 PgBouncer。Atlas 在运行期间持有的 咨询锁是会话级锁,而这些连接池代理会将其丢弃;Supabase 和 Neon 都建议迁移使用直接连接。 - 某些更改需要手动编辑生成的迁移(
references/objects.md):- PostgreSQL 无法隐式执行的类型转换,例如从
text转为integer或uuid,需要USING子句。 - 将已有数据的列转换为
serial时,需要使用setval,否则插入会因键重复而失败。 - 从
serial转为bigserial时,需要使用ALTER SEQUENCE ... AS bigint,否则序列仍会在 2147483647 处停止。 - 新的枚举值应放在一个文件中添加,并在后续文件中首次使用。删除或重新排序枚举值需要手写迁移, 而其计划可能报告无更改。
- PostgreSQL 无法隐式执行的类型转换,例如从
- 养成习惯:在报告完成之前测试每项更改。运行
atlas schema validate;为添加或更改的每个函数、 触发器、视图、域、检查约束或策略添加一个test "schema"用例;为每个移动或转换数据的迁移 添加一个包含预置行的test "migrate"用例。使用atlas schema test和atlas migrate test运行测试(references/testing.md)。 - 如果没有内置分析器可用于某项检查,请使用 HCL 规则语言编写自定义 lint 规则;对于用户提出的约定,
也应如此,例如要求每张表都启用行级安全,或为每个外键建立索引。规则可以检查 Atlas 检查的任意对象的
任意属性,而 lint 会在每次更改时强制执行这些规则(
references/custom-rules.md)。
Quick Answers
| 问题 | 解答 |
|---|---|
| 用于应用迁移的本地 PostgreSQL 数据库 | atlas tool docker --url "docker://postgres/17/myapp?search_path=public" --name my-db 会打印其 URL;atlas tool docker kill --name my-db 会将其停止(references/dev-database.md) |
cannot drop type ... because other objects depend on it,或视图和函数未出现在计划中 | 运行 atlas whoami:如果已退出登录,Atlas 会跳过视图和函数,包括依赖该类型的对象(规则 1) |
| 在 Supabase、Neon 上或使用 PgBouncer 时,应向 Atlas 提供哪个 URL | 使用直连,不要使用事务模式的连接池代理(references/migrations.md,Connection Poolers) |
pq: unsupported startup parameter: search_path | URL 经过了 PgBouncer;请使用直连(references/migrations.md,Connection Poolers) |
迁移中缺少 CREATE EXTENSION | URL 仅限定到架构;扩展需要数据库级作用域(references/dev-database.md) |
计划会删除 public 架构 | 在数据库级作用域下,期望状态涵盖所有架构:声明 schema "public" {},或使用架构级 URL(references/dev-database.md) |
cannot diff a schema with a database connection | URL 与开发 URL 的作用域不同(references/dev-database.md) |
connected database is not clean | dev 指向的数据库不为空(references/dev-database.md) |
| 每个计划中都出现相同的变更 | 设置一个与目标作用域一致的开发 URL:Atlas 会在该 URL 上规范化默认值和表达式(references/dev-database.md) |
某列未经请求就变成了 NOT NULL | HCL 列默认为 NOT NULL,除非设置了 null = true(references/hcl.md) |
ALTER COLUMN ... TYPE 在将 text 转换为 integer 或 uuid 时失败 | 在迁移文件中添加 USING 子句(references/objects.md,Column Changes) |
某列变成 serial 后,插入操作因键重复而失败 | 使用 setval 移动序列(references/objects.md) |
| 某个枚举值已被移除,但差异报告没有变更 | 不会规划枚举值的移除:请手动编写变更(references/objects.md,Enums) |
unsafe use of new value | 将枚举值的添加和首次使用分别写入不同的迁移文件(references/objects.md,Enums) |
pq: type "geometry" does not exist | 在架构或开发环境的 baseline 中创建扩展;仅使用 PostGIS 镜像并不会安装扩展(references/dev-database.md) |
Lint 对索引报告 PG101 或 PG103 | 使用 concurrent_index 策略或 atlas:txmode none(references/migrations.md) |
| 某项约定必须适用于每张表,例如行级安全或外键索引 | 编写自定义 lint 规则(references/custom-rules.md) |
| 行级安全测试无论策略如何设置都会通过 | 开发数据库以超级用户身份连接,该用户会绕过策略;请使用非特权角色进行测试(references/testing.md) |
pq: unexpected transaction status idle | 从文件中移除 BEGIN/COMMIT:Atlas 已在事务中运行迁移(references/migrations.md) |
更改 URL 的作用域后出现 ambiguous revision table | 将 --revisions-schema 设置为存放现有表的架构(references/migrations.md) |
分区表出现 DROP and CREATE is required | 更改分区键或对现有表进行分区,需要手动编写迁移(references/objects.md) |
开发数据库出现 ERROR: out of shared memory | 在 docker 块中将 max_locks_per_transaction 提高到 128 以上(references/dev-database.md) |
| 迁移中缺少事件触发器 | 使用数据库级开发 URL(references/objects.md) |
每个计划都会撤销 postgres(Cloud SQL)、RDS 主用户或其他提供商管理员的权限 | 通过开发数据库生成计划,并确保其中的管理员是普通角色(references/security.md,Managed Providers) |
新角色需要对数千张表执行 SELECT | 将其设为 pg_read_all_data 的成员,而不是逐表授予权限(references/security.md) |
开发数据库中的对象属于 postgres,但生产环境有其他所有者 | 所有者不属于期望状态(references/security.md,Ownership) |
迁移中没有 ALTER DEFAULT PRIVILEGES | 这是预期行为:Atlas 会按对象规划其所隐含的 GRANT(references/security.md) |
对序列的授权使 bigserial 列变成了 bigint | 这是预期行为:现在会显式管理该序列(references/objects.md) |
文档
- PostgreSQL HCL 参考:https://atlasgo.io/hcl/postgres
- 开发数据库:https://atlasgo.io/concepts/dev-database
- 安全性:https://atlasgo.io/guides/postgres/security-declarative, https://atlasgo.io/guides/postgres/security-default-privileges
- 锁安全变更:https://atlasgo.io/guides/lock-safe-not-null, https://atlasgo.io/lint/analyzers
- 各数据库指南:https://atlasgo.io/databases
评论
支持 Markdown