<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Dbmate on ShawnDeng's Tech Blog</title><link>https://shawndeng.tech/tags/dbmate/</link><description>Recent content in Dbmate on ShawnDeng's Tech Blog</description><generator>Hugo -- 0.146.0</generator><language>zh-cn</language><lastBuildDate>Fri, 24 Jul 2026 10:00:00 +0800</lastBuildDate><atom:link href="https://shawndeng.tech/tags/dbmate/index.xml" rel="self" type="application/rss+xml"/><item><title>数据库结构版本管理</title><link>https://shawndeng.tech/posts/database-migration-guide-for-beginners/</link><pubDate>Fri, 24 Jul 2026 10:00:00 +0800</pubDate><guid>https://shawndeng.tech/posts/database-migration-guide-for-beginners/</guid><description>&lt;h2 id="为什么数据库也需要版本管理">为什么数据库也需要版本管理？&lt;/h2>
&lt;p>假设你开发新功能时，在本地执行了：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ALTER&lt;/span> &lt;span style="color:#66d9ef">TABLE&lt;/span> users &lt;span style="color:#66d9ef">ADD&lt;/span> &lt;span style="color:#66d9ef">COLUMN&lt;/span> nickname VARCHAR(&lt;span style="color:#ae81ff">100&lt;/span>);
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>代码提交并部署到测试环境后，接口却报错：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>column &amp;#34;nickname&amp;#34; does not exist
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>原因很简单：代码进入了 Git，修改数据库的 SQL 却只存在于你的电脑里。&lt;/p>
&lt;p>如果数据库变更依靠聊天记录或人工执行，我们就很难回答：&lt;/p>
&lt;ul>
&lt;li>哪些环境执行过这条 SQL？&lt;/li>
&lt;li>新环境应该按什么顺序初始化？&lt;/li>
&lt;li>测试库和生产库的结构是否一致？&lt;/li>
&lt;li>三个月前为什么增加了这个字段？&lt;/li>
&lt;/ul>
&lt;p>解决办法是 &lt;strong>DB Migration（数据库迁移）&lt;/strong>：把每次数据库结构变化写成带版本号的文件，提交到 Git，再由工具按顺序执行。&lt;/p>
&lt;hr>
&lt;h2 id="migration-是怎样工作的">Migration 是怎样工作的？&lt;/h2>
&lt;p>可以把 Migration 理解成“数据库的 Git Commit”：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>20260724100000 创建 users 表
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>20260724103000 增加 nickname 字段
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>20260724110000 创建邮箱索引
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>迁移工具会：&lt;/p>
&lt;ol>
&lt;li>读取 Migration 目录；&lt;/li>
&lt;li>查询数据库已经执行的版本；&lt;/li>
&lt;li>按顺序执行尚未执行的文件；&lt;/li>
&lt;li>记录成功执行的版本。&lt;/li>
&lt;/ol>
&lt;p>几个容易混淆的概念：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>概念&lt;/th>
&lt;th>用途&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Migration&lt;/td>
&lt;td>记录数据库如何一步步变化&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Schema 快照&lt;/td>
&lt;td>展示数据库当前的完整结构&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>数据备份&lt;/td>
&lt;td>在数据损坏或丢失后恢复&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Migration 不能代替备份。执行 &lt;code>DROP COLUMN&lt;/code> 后，Down Migration 也不一定能找回已经删除的数据。&lt;/p>
&lt;p>ORM 自动建表也不完全等于版本管理。ORM 可以帮助生成 Migration，但共享环境最好执行已经生成、评审并提交到 Git 的确定性 SQL，而不是在应用启动时临时修改数据库。&lt;/p></description></item></channel></rss>