前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
返回 AI 情报前线
All News · 全部资讯9258
  • AI Agent 越界行动:英国安全研究院报告
  • Lovable应用移植React Native的组件对照表
  • 2026年用10美元预算开发AI SaaS原型完整指南
  • 2026 年 GPU 选型指南:H100 与 A100 成本效益对比
  • AI Agent 测试方法论:从单元测试到混沌工程
  • AI Skill跑通一次不算测试
  • 用Milvus+Ollama自建私有RAG实战
  • 上下文窗口不是记忆:AI Agent 记忆机制的深层误解
  • 上下文窗口不是记忆:AI Agent 记忆机制的深层误解
  • 智谱 GLM-5.3 发布:编程能力最强开源模型,Terminal-Bench 得分暴涨 5 倍
  • LLM 可解释性实战:用 Sparse Autoencoder 破解 Transformer 黑盒
  • Gemini 3.7 Flash发布,Google AI开发重回焦点
  • AI编程时代:系统设计比写代码更重要
  • 智谱GLM 5.3正式发布,推理能力与效率进一步提升
  • 十七行Python检查LLM网关是否抽成
  • LLM选型矩阵:按功能挑最便宜可靠模型
  • Figma MCP 做 UI 代码:截图只能验证布局,数值必须从节点读取
  • 苹果在中国训练本地AI模型,集成阿里千问
  • Obsidian Skills:让 AI 编程助手读懂你的笔记库
  • 一行Python代码构建OpenAI兼容网关,支持多模型代理
  • AI 生成数据库迁移的正确姿势:先在临时库重放验证
  • holaOS:一个空间运行任意 Agent,共享记忆
  • AI 代码补丁三验 Loop:合同、执行、回归
  • 用 AI 给 CI 失败先分类再读日志
  • AI 时代面试已失效:会做题≠会工程
  • DeepSeek V4-Pro 对 token 上限参数置若罔闻
  • Unsloth Desktop:本地一键跑大模型和训练,集成Claude Code/Codex/MCP
  • AI 在自动化工作流中的四种核心角色
  • ChatGPT工作原理深度解析
  • 通过单一Chatbot API接入三个降级模型:JSON Schema校验与回退策略
  • LLM 工单分类实战:用 JSON Schema 控制输出+重试+成本计量
  • Node.js 应用添加 OpenAI 兼容模型降级方案
  • 成功 AI 产品中反复出现的 3 种 Agent 模式
  • GitHub Copilot 8月10日更新:便携插件与Agent工作流
  • 未提供的上下文会被模型自行补全——这是安全漏洞的根源
  • 从零构建推理小模型:SupraLabs 推理语料流式微调实战
  • 金额不能用浮点数:AI演示里那个隐藏的经典Bug
  • Google 发布 Gemini 3.7 Flash:编程能力提升33%,$0.75/1M tokens
  • 何时该用LangGraph而非简单Tool-Calling
  • AI 生成代码:看起来对≠真的对
  • AI Agent 实战:七个生产环境失败模式及修复方案
  • Cerebras + OpenAI 实现 750 tokens/s 推理
  • 架构文档约束失效,AI 编程代理的隐性风险
  • AI编程工具成团队依赖瓶颈:Copilot用尽后的协作困境
  • OpenAI 收购 Astral:Python 基础设施可能被重构
  • AI 蠕虫已真实存在:多伦多大学 self-replicating 攻击研究解析
  • DeepSeek V4:稀疏注意力实现低成本百万 token
  • 别把巨型 OpenAPI spec 一股脑塞给 AI Agent
  • Biome:56 倍速替代 ESLint+Prettier 的 Rust 工具链
  • 为何每个AI Agent不应重复学习你的数据模型
  • DeepSeek Harness预览:模型评测与部署框架完整指南
  • 已加载 51 / 9258
8.0
热点
AI SCORE
技术实践2026-08-14 12:27

AI 生成数据库迁移的正确姿势:先在临时库重放验证

dev.to · AI#数据库#AI工具#DevOps
Editor brief · 编辑速览

用独立验证工具对 AI 生成的迁移脚本在临时 SQLite 数据库上重放,拦截无回滚证据的危险操作,避免生产事故。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

AI 辅助数据库工作最难的部分不是生成迁移,而是判断这条迁移能否在真实的数据库引擎上存活。文本 review 能发现缺失的索引或可疑的命名规范,但往往漏掉真正重要的失败场景:比如一条 DROP COLUMN 作用在某后台任务仍在查询的列上,或者一条 DELETE 在本地能跑通但在带有生成列的表上却不行。

当前关于限制 AI 工具的讨论通常集中在权限层面。这很重要,但对数据库工作来说,更实用的切分点是确定性验证。模型提出一个变更;一个独立的、枯燥的验证工具在独立环境中让这个变更证明自己可行,然后才需要人介入判断。

本文展示了一个完成上述工作的轻量验证工具。它接收一条生成的迁移,在临时 SQLite 数据库上执行它,拒绝没有回滚证据的危险语句,并在任何一步失败时以非零退出码退出。重点不在于具体的 SQL 方言,而在于提案和验证保持分离。

免费模型 + 免费服务器适合的场景

一个实用的方案是:用 MonkeyCode 的免费模型起草迁移,用它的免费服务器选项运行 replay 套件。声明:本文作为 MonkeyCode 产品推广的一部分撰写。但这个验证工具本身是提供商无关的。你可以把生成器指向任何你已在用的端点,也可以把验证工具跑在本地、CI 或常驻服务器上。

模型对快速产出初稿很有用,但它不是证明正确性的合适地方。模型可以生成在本地能解析的 SQL,却仍然会删除一个列、锁住一张大表,或违反一个只在生产环境存在的约束。这些失败是确定性的,所以应该由确定性的代码来检查。

保存为 prove_migration.py。

#!/usr/bin/env python3
import subprocess
import sys
import tempfile
from dataclasses import dataclass

@dataclass
class CheckResult:
    name: str
    passed: bool
    detail: str

def run(cmd, cwd, timeout=120):
    return subprocess.run(
        cmd,
        cwd=cwd,
        capture_output=True,
        text=True,
        timeout=timeout,
    )

def make_scratch_db(kind='sqlite'):
    if kind == 'sqlite':
        tmp = tempfile.mkdtemp()
        return tmp, f'{tmp}/scratch.db'
    raise NotImplementedError('swap in a Postgres container for non-SQLite checks')

def parse_migration(patch):
    # Simplified. A production guard should use a real SQL parser.
    statements = [s.strip() for s in patch.split(';') if s.strip()]
    if not statements:
        raise ValueError('no statements found')
    return statements

def is_destructive(statement):
    lowered = statement.lower()
    destructive_markers = ['drop table', 'drop column', 'delete ', 'truncate']
    return any(marker in lowered for marker in destructive_markers)

def check_migration(patch):
    results = []
    db_dir, db_path = make_scratch_db()

    baseline_schema = 'CREATE TABLE orders(id INTEGER PRIMARY KEY, status TEXT);'
    baseline = run(['sqlite3', db_path, baseline_schema], db_dir)
    results.append(CheckResult('baseline_schema', baseline.returncode == 0, baseline.stderr.strip()[:200]))

    statements = parse_migration(patch)
    for index, statement in enumerate(statements, start=1):
        result = run(['sqlite3', db_path, statement], db_dir)
        detail = statement[:80]
        if result.returncode != 0:
            detail = result.stderr.strip()[:300]
        results.append(CheckResult(f'statement_{index}', result.returncode == 0, detail))

    for statement in statements:
        if is_destructive(statement):
            results.append(CheckResult(
                'rollback_guard',
                False,
                f'destructive statement has no rollback evidence: {statement[:80]}',
            ))

    return results

def prove_patch(patch):
    results = check_migration(patch)
    for result in results:
        status = 'PASS' if result.passed else 'FAIL'
        print(f'[{status}] {result.name}: {result.detail}')
    return all(result.passed for result in results)

if __name__ == '__main__':
    patch = sys.stdin.read()
    ok = prove_patch(patch)
    sys.exit(0 if ok else 1)

通过管道把生成的迁移传入标准输入来运行:

python prove_migration.py < candidate_migration.sql

一条添加列的非危险迁移会通过。即使 SQLite 接受了该语句,包含裸 DROP COLUMN 的迁移也会触发回滚守卫而失败。这种"粗暴"是刻意设计的。危险变更永远不应该仅仅因为语法没问题就放行。

如果你的笔记本在 replay 过程中总是进入睡眠,同样的脚本可以在免费服务器上运行。唯一真正的依赖是 Python 运行时和目标数据库引擎。长时间运行的 replay 套件更适合无人值守的服务器,而不是随时可能合上盖子的笔记本。

让验证比模型更严格

最重要的设计选择是:模型不参与验证循环。不要让一个模型生成迁移,然后又让一个模型在没有可执行中间步骤的情况下去 review 它。模型可以自信地错两次。验证工具应该是笨拙的、可读的,并且对补丁文本听起来多有说服力漠不关心。

一个有用的起步规则集如下:

表格故意设得保守。在看到误报后再放宽规则,比事后发现危险迁移漏了过去要容易得多。

这解决不了什么

这个验证工具不是真正的迁移工具的替代品。简单的分号分割器会无法处理字符串、函数或过程化 SQL 内部的冒号。SQLite 临时数据库无法捕获只在 Postgres、MySQL 或特定扩展中才会出现的行为。回滚守卫是启发式的;它拦截明显的危险语句,但不会重建回滚计划或验证时间点恢复。

它也不能保护那些语法正确但语义错误的生成 SQL。模型可能添加了类型错误的列,而临时数据库会接受它。这仍然需要人来将变更与需求意图进行对比。

最后,不要对包含真实客户数据的数据库运行不受信任的生成 SQL。临时数据库应该始终是可丢弃且隔离的。

谁不应该用这个方案

对每条迁移都有强制数据库管理员 review 的团队,可能会觉得这个工具作为 pre-review 过滤器仅略有帮助。在受监管的 schema 上,或生产迁移需要时间点恢复的团队,应该保留现有的变更管理流程,只把这个工具当作本地合理性检查。如果你已经有了付费 CI runner 和成熟的迁移流水线,可能不再需要单独的免费服务器来执行 replay 步骤,尽管这个验证工具本身仍然值得复制。

值得保留的部分

模型是可以替换的。验证工具才是持久的产物。一条提议的迁移应该在临时数据库上通过 replay,识别出任何缺少回滚证据的危险语句,并在人工介入 review 之前产生机器可读的成功或失败信号。如果你维护的是迁移密集型的代码库,验证工具是值得复制的部分;模型可以保持廉价且可替换。

Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
一行Python代码构建OpenAI兼容网关,支持多模型代理
下一篇
holaOS:一个空间运行任意 Agent,共享记忆