<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>嵌入式数据库 &#8211; mylogs.cn</title>
	<atom:link href="https://mylogs.cn/tag/%e5%b5%8c%e5%85%a5%e5%bc%8f%e6%95%b0%e6%8d%ae%e5%ba%93/feed/" rel="self" type="application/rss+xml" />
	<link>https://mylogs.cn</link>
	<description>发现、记录、分享</description>
	<lastBuildDate>Wed, 12 Aug 2026 15:31:36 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>Tailscale 半年排查，揪出潜伏 16 年的 SQLite 漏洞</title>
		<link>https://mylogs.cn/tailscale-sqlite-16-year-wal-bug/</link>
		
		<dc:creator><![CDATA[steve, zhang]]></dc:creator>
		<pubDate>Wed, 12 Aug 2026 15:31:22 +0000</pubDate>
				<category><![CDATA[科技]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[Tailscale]]></category>
		<category><![CDATA[WAL 预写日志]]></category>
		<category><![CDATA[嵌入式数据库]]></category>
		<category><![CDATA[数据库损坏]]></category>
		<category><![CDATA[漏洞修复]]></category>
		<category><![CDATA[竞态条件]]></category>
		<guid isPermaLink="false">https://mylogs.cn/tailscale-sqlite-16-year-wal-bug/</guid>

					<description><![CDATA[一家以网络工具著称的公司，花了半年时间追查自家生产环境里反复出现的数据库损坏，最终定位到一个潜伏了十六年的底层 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">一家以网络工具著称的公司，花了半年时间追查自家生产环境里反复出现的数据库损坏，最终定位到一个潜伏了十六年的底层漏洞。这个漏洞不在 Tailscale 自己的代码里，而在几乎所有人都信赖的嵌入式数据库 SQLite 之中。</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6a7c9bb7a59e2&quot;}" data-wp-interactive="core/image" data-wp-key="6a7c9bb7a59e2" class="wp-block-image size-large aligncenter wp-lightbox-container"><img fetchpriority="high" decoding="async" width="1200" height="630" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://mylogs.cn/wp-content/uploads/2026/08/991015ebe84b149917d7bc9c38d8568d_header.webp" alt="Tailscale 半年排查，揪出潜伏 16 年的 SQLite 漏洞" class="wp-image-4598" style="max-width:100%;height:auto;" srcset="https://mylogs.cn/wp-content/uploads/2026/08/991015ebe84b149917d7bc9c38d8568d_header.webp 1200w, https://mylogs.cn/wp-content/uploads/2026/08/991015ebe84b149917d7bc9c38d8568d_header-300x158.webp 300w, https://mylogs.cn/wp-content/uploads/2026/08/991015ebe84b149917d7bc9c38d8568d_header-1024x538.webp 1024w, https://mylogs.cn/wp-content/uploads/2026/08/991015ebe84b149917d7bc9c38d8568d_header-768x403.webp 768w" sizes="(max-width: 1200px) 100vw, 1200px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">图片来源：Tailscale</figcaption></figure>





<h2 class="wp-block-heading">半年拉锯：控制平面的数据库为何频频损坏</h2>



<p class="wp-block-paragraph">Tailscale 的工程师团队在排查中发现，公司的控制平面（control plane）数据库会间歇性地出现损坏，进而导致服务不稳定。这段时间里，客户和员工都深受其扰，而问题却像捉迷藏一样时隐时现——曾有连续六周的「虚假平静」，让团队一度以为已经修好。</p>



<p class="wp-block-paragraph">真正的突破口，来自对 SQLite 预写日志（Write-Ahead Log，简称 WAL）机制的一次深入剖析。WAL 是现代 SQLite 在写入数据时采用的模式：新数据先追加到日志文件，再由「检查点」（checkpoint）操作把日志内容正式写回数据库主文件。Tailscale 团队发现，当一次写入事务与一次 WAL 重置（WAL-reset）发生在极短的时间窗口内重叠时，就会触发一个边界情况的竞态条件，进而让索引与数据不同步，最终造成数据库损坏。</p>



<h2 class="wp-block-heading">漏洞藏在 WAL 重置的瞬间</h2>



<p class="wp-block-paragraph">问题的精确触发条件相当苛刻：一个连接正在执行检查点操作，且这次检查点必须顺利完成；紧接着第二个检查点启动，而在它运行期间，另一个数据库连接提交了一笔事务，把 WAL 文件冲刷一遍并向文件开头写入了新内容。由于数据访问发生冲突，第二个检查点没有意识到 WAL 文件已被那笔事务冲刷过，于是在 WAL 索引头里写入了错误的字段值，误以为部分事务已经提交。后续再有事务提交时，WAL 文件里的页数超过了第一次检查点时的页数，等到第三次检查点发生时，第二步写入的那部分事务被整段跳过，永远没能进入数据库主文件，损坏就此产生。</p>



<p class="wp-block-paragraph">更令人意外的是，这个漏洞影响范围极广。它存在于自 SQLite 3.7.0（发布于 2010 年 7 月 21 日）起、直到 3.51.2 的所有版本。也就是说，十六年来几乎所有基于 WAL 模式的 SQLite 部署都携带这一隐患。修复先是在 3.51.3 版本（2025 年 3 月）中落地，部分较早版本也拿到了热修复补丁（3.44.6 与 3.50.7）。后续的 3.53.0 版本还新增了自动自愈的索引功能，从机制上防止过期表达式索引再次引发同类问题。</p>



<h2 class="wp-block-heading">Tailscale 为何偏偏踩中：偏离了「标准路径」</h2>



<p class="wp-block-paragraph">值得玩味的是，绝大多数开发者从未遇到这个问题。SQLite 拥有远超代码量的测试套件，被公认为软件可靠性的标杆。Tailscale 之所以中招，是因为他们以非标准的方式使用了这项「无聊的技术」：团队手动接管了检查点过程，并按照自己激进的节奏来运行，从而踏上了常规配置之外的小径。</p>



<p class="wp-block-paragraph">整个排查是一场跨职能的苦战，动用了数十人，包括 Tailscale 的工程与客服团队，以及 SQLite 的核心维护者。为了隔离这个竞态条件，Tailscale 还资助了一个开源的 SQLite VFS（虚拟文件系统）中间层工具，帮助在未来追踪类似问题。</p>



<h2 class="wp-block-heading">等了两个月，才等来那声「令人愉快的警报」</h2>



<p class="wp-block-paragraph">为了拿到生产环境确实发生该竞态的正面证据，Tailscale 在自家的 SQLite 驱动里打了补丁：当写入事务与 WAL 重置重叠时，记录一条警告。随后便是漫长的等待——两周、一月、两月。就在团队开始怀疑补丁是否失效、理论是否出错时，那条等待已久的警报终于触发，证明这个精确条件在真实生产环境中确实会出现。此后，系统又平稳运行了四个月，再无数据库事故。</p>



<h2 class="wp-block-heading">启示：成熟技术也怕「非常规用法」</h2>



<p class="wp-block-paragraph">这起事件给工程界提了个醒：运行成熟技术时，如果脱离常规配置、以非标准方式使用，风险会被悄然放大。常见的路径和标准配置经过了极其充分的测试，可靠性很高；而一旦为了性能或控制力手动接管底层机制，就必须为那些「几乎不可能发生」的边缘错误做好准备。对依赖 SQLite 存储关键数据的系统而言，定期执行完整性校验、保留可靠的备份与恢复流程，依旧是必要的兜底手段。</p>



<p class="has-small-font-size wp-block-paragraph">来源：Tailscale 工程博客《How we tracked down a 16-year-old SQLite bug》</p>

]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
