MoreRSS

site iconSanguok | 山月修改

※興趣 ①閩語 ②文言 ③漢字 ④東亞各種文獻 ⑤劇畫稗玩/ACGN ⑥平面設計與排印
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Sanguok | 山月的 RSS 预览

控制笔记本温度与风扇噪音——以ASUS GL553VD为例

2025-06-12 21:27:41

前言

这几年笔记本电脑性能越来越强,但玩游戏或者跑大软件的时候,发热和风扇吵的问题也越来越厉害了。本文以陪伴了笔者多年的老机——ASUS GL553VD笔记本(i7-7700HQ + GTX 1050/1060)为例,汇总了从安装环境XTU/ThrottleStop调控、GPU控制风扇曲线、自动启动到硬件维护的完整降温降噪方案,附带各项技术细节,帮助追求静音与性能平衡的朋友们。


一、环境准备与兼容性解决

1. Intel XTU安装故障排查

Intel XTU(Extreme Tuning Utility)是英特尔官方推出的一款Windows平台下的系统级调校软件,允许用户对CPU的频率、电压、功耗等参数进行实时监控与精细调节,以追求更高性能或更低温噪。

当然,在安装它的过程中,可能会遇到报错。Intel XTU倘安装失败,是会输出日志文件,并弹窗提示用户查阅的(这点比隔壁NVIDIA要好太多)。最常见的是:

  • 错误码:0x80070643
    • 关键的报错信息(可以在日志里头找到):e000: Error 0x80070643: Failed to install MSI package.
    • 错误代码0x80070643是Windows Installer通用的“致命错误”,通常意味着:
      • 系统有待重启的更新或操作未完成(日志里也有RebootPending = 1);或者是
      • 先前安装残留或锁定了某些文件/注册表;要不然则
      • 安装程序权限不足或某个依赖(.NET Framework、VC++运行时)损坏。
  • 解决思路
    1. 重启系统,清除挂起更新;
    2. 确保.NET Framework ≥ 4.7.2、VC++ 2015-2022运行库完整;
    3. 以管理员模式运行安装程序。(值得一试!)

在经过上述排查后,倘若还是无法正确安装,那么可能是所使用的电脑系统版本、CPU型号、世代等不支持使用中的Intel XTU安装包。以笔者的情况为例,从官网下载到的最新版的Intel XTU(笔者写作当时下载的是2025年夏释出的10.0.1.31版)就无法正常安装,会提示曰——不适应当前的platform(平台)。好在官网提供两种下载包:

下面是两个版本的英特尔® XTU,版本 7.14.2.45 支持未锁频的英特尔® 酷睿™处理器(第 14 代)和更早的处理器,而版本 10.0 支持未锁频的英特尔® Core™ Ultra处理器(系列 2)及更高版本。

英特尔® Extreme Tuning Utility (英特尔® XTU)下载页面

所以选择去下载支持早期处理器的最终版本就好了。笔者的实测,也是能够无报错地顺利安装的。

2. XTU与VBS冲突

Unable to start Intel(R) Extreme Tuning Utility because of a system incompatibility.

XTU is incompatible with Windows VBS (Virtualization-based security).

Your CPU/BIOS does not have Undervolt Protection support as a mitigation, so you should check the status of services that can enable VBS. Click here to read more about Windows features that can enable VBS.

Click here to check the status of Windows VBS.

Consult the XTU documentation for more information.

Disabling Windows services or features may affect the functionality of other applications.

弹窗提示文本
  • 如上所示,Windows VBS(虚拟化安全)与XTU不兼容,会直接在尝试双击打开XTU后弹窗提示“CPU/BIOS does not have Undervolt Protection support”(CPU/BIOS不支持Undervolt Protection)而无法启动。
  • 解决
    1. 关闭核心隔离 → 内存完整性(Memory Integrity)
    2. (或者)PowerShell执行:
      # 关闭 Hyper-V
      dism.exe /Online /Disable-Feature:Microsoft-Hyper-V

      # 关闭 Windows Hypervisor Platform(如果启用了的话)
      dism.exe /Online /Disable-Feature:VirtualMachinePlatform
      命令执行完成后再重启。
      或者在提升权限的命令行里执行:
      bcdedit /set hypervisorlaunchtype off
      然后重启。
    3. (可选)组策略:
      • Win+R→ 输入gpedit.msc打开组策略编辑器
      • 计算机配置 → 管理模板 → 系统 → Device Guard → 禁用 “Turn On Virtualization Based Security”。
      • 重启

关闭VBS/Hyper-V会降低一部分系统安全(如HVCI、Credential Guard等保护功能),请权衡风险。这里提示:若不想关闭VBS,其实也未必要用XTU,直接使用下文的ThrottleStopNVIDIA Inspector等工具替代。

笔者的情况,是即便尝试关闭了Windows安全下的“内存完整性”设置,也无法通过XTU做任何调整电压的设置,所以只能放弃。

笔者打开XTU主界面后,迎面而来的是:

  • Power & Current Limits Optimized(一键优化电源和电流限制)与
  • Run Benchmark(内置基准测试)

俩按钮。Power & Current Limits Optimized系官方推荐之快速模式。按道理第一次调试前得先跑一次基准(Run Benchmark)并保存得分;再启用这个一键优化模式再跑一次:观察它给到的“预设优化”能带来多少收益。

这是一张XTU主界面的截图。反映了在笔者电脑上,Power & Current Limits Optimized按钮是灰色的,不能点。点击旁边的信息提示按钮ⓘ,指出:如果想超频,需要在Advanced View里对核心倍频和电压做小幅度调整。(但由于笔者的i7-7700HQ并不是K系列,倍频是锁死的,无法像台式K系列那样真正超频。所以按钮会灰掉。)在主界面没事儿可做,遂随便跑了下Run Benchmark,得分1127。
但是,XTU主界面提示倍频是锁死的

但是在笔者电脑上,Power & Current Limits Optimized按钮是灰色的,不能点。点击旁边的信息提示按钮,指出:如果想超频,需要在Advanced View里对核心倍频和电压做小幅度调整。但由于笔者的i7-7700HQ并不是K系列,倍频是锁死的,无法像台式K系列那样真正超频。所以按钮会灰掉。

在主界面没事儿可做,遂随便跑了下Run Benchmark,得分1127

左下角还有个Advanced View按钮,能展开更多的配置选单。点击后默认是System Infomation标签页,展示系统信息的。在左侧蓝色栏里,点击第二项Advanced Tuning(高级调校),尝试切过去——结果该标签页下一片空白。按道理在这里能做以Processor Core Voltage Offset(核心电压偏移)为首的Processor Core(处理器核心)设置,但是笔者这边就是没有。这一般不是软件错乱,而是笔者这台机子/BIOS微码把所有MSR可调寄存器都锁死了——XTU本身没东西可以调,自然就返回一片空白。


二、ThrottleStop深度调控

ThrottleStop是Windows下最强大的Intel CPU调控利器,能针对功耗、频率、电压进行细致调整。笔者此次安装了ThrottleStop 9.7版本。

主界面

1. 基本界面与配置档

主界面左上四个可选按钮代表4个profile,可以挑一个觉得名字合适的profile(或者把其中一个profile直接通过设置页改名),以进行后续的操作。

切档流程:选中按钮 → 修改参数 → SaveTurn On

下面开始介绍具体的配置方法。这里先且总结一下思路:

  1. EPP+低PL1/PL2+短冲刺时长 → 大幅降低平均功耗与温度,噪音跟着掉。
  2. 保留SpeedStep+C1E可确保空闲时更低功耗。
  3. 如果温度/噪音还高,可再小幅下调PL1(例如35W),或把EPP调到255

每次改完记得跑个短压测(如TS Bench、Prime95、3DMark)看温度/频率,找到「性能‐噪音‐温度」的最佳平衡点。

2. 主界面“Performance”区设置

  1. SpeedShift EPP:勾选它,然后把右边128的数值调高到200240(越大越偏向节能、低温)。
    • 注意,数字的修改,这边没有什么拖动条,而是直接将光标移动到数字上面,单击,然后编辑文本。
  2. SpeedStep & C1E:都勾上,让空闲时进深度节电态。
  3. BD PROCHOT:勾选,可以让CPU感知到VRM/芯片组的过热并配合降频(更安全);如果愿意稍微冒点风险,也可以先不勾。
  4. Disable Turbo要勾,这样还能保留短暂冲刺;真正靠下面的功耗限制来控温。

勾完以后,点左下的Save

3. FIVR:轻度降压(Undervolt)

  1. 点击FIVR → 勾选 Core & Cache 的 “Unlocked” → Offset Voltage 设为 –80 mV ~ –120 mV
  2. ApplySave

效果:核心与缓存双降压,稳态降温 5–10 ℃。

4. TPL:功耗极限控制

TPL设置界面
  1. 点击TPL打开 “Turbo Power Limits”。
  2. 取消Disable Controls,勾选并设置:
    • Long Power PL1 = 45 W + Clamp
    • Short Power PL2 = 60 W + Clamp
    • Turbo Time Limit = 10–15 s
  3. ApplyOK → (主界面)Save

效果:短时冲刺后迅速回到45 W,显著降低平均功耗与温度。

5. C-States & SpeedShift

  • 勾选C1E / C10:空闲时迅速进入深度睡眠态。
  • 勾选SpeedStep,保留涡轮但优先调度低频率。
  • Clock Mod(80–90%)或Set Multiplier:进一步锁频,必要时可用。

5. 启动与自动加载

ThrottleStop 9.7取消内置开机启动,推荐:

方法一:启动文件夹

Win+R → shell:startup
在此文件夹新建ThrottleStop.exe快捷方式,并在Options勾选Start Minimized

方法二:任务计划

  • 触发器:登录时;
  • 操作:启动ThrottleStop.exe,参数-minimized
  • 属性:以最高权限运行。

三、NVIDIA GPU节能调控

使用NVIDIA Inspector这款软件。

  1. Profile选_GLOBAL_DRIVER_PROFILE
  2. Sync and Refresh → Frame Rate Limiter,设60–75 FPS
  3. PowerMizer → Preferred Mode → Adaptive(自适应)或Optimal Power
  4. Overclock(若可):GPU Clock Offset、Mem Clock Offset设置为负值。
  5. Apply changes

四、风扇控制:Fan Control软件

Fan Control V226软件界面

使用开源的Fan Control(笔者用的是FanControl V226)替代BIOS风扇曲线(既然BIOS改不了的话),具体配置:

参数 建议值 说明
关闭温度 45 ℃ 非负载时保持静音
最小速度 10 % 风扇最低档
步进 (Step) 1 %/s 平滑升降
死区 (Dead) 2 ℃ 避免频繁抖动
负载温度 75 ℃ 达到此温度开始冲档
最大速度 80 % 保证足够散热,同时控制噪音
响应时间 1 s 温度变化后 1 秒再调速

高级方案:再建一条高负载曲线(负载温度85℃ → 最大100%),切换profile实现静音与散热兼顾。


五、BIOS / Armoury Crate 风扇曲线

笔者的情况下,BIOS无法修改风扇曲线。如果要尝试修改的话,可采取以下思路:

  • 进BIOS → Q-Fan Control → 选择Silent或自定义:
    • 低档起转:50℃ → 最高60–70%;
    • 确保重负载时仍保有散热余量。

六、系统电源计划微调

  • 处理器最大状态设为99%,禁止无限制Turbo;
  • 系统散热策略设为被动
  • 选用平衡省电方案,进一步降低功耗。

七、硬件维护与辅助散热

  1. 清灰重涂:清洁散热鳍片、风扇,重贴高端硅脂,降温3–5℃;
  2. 散热底座:选购带大风扇的底座,底部增风。
  3. 保持进风口与排风口通畅,避免堵塞。

结语

通过软件+固件+硬件三管齐下的方式,从CPU功耗、电压限制,到GPU节能配置,再到风扇曲线系统策略,你可以将笔记本的温度与噪音控制在一个令人满意的水平,同时不损失过多性能。每台机器与环境不同,建议分档测试压测(TS Bench、3DMark、FurMark、游戏),逐步微调,找到最适合你的平衡点。

祝你的笔记本静音顺畅,性能在线!

如何优雅地升级ruby标签:正则表达式指南

2025-06-09 20:32:11

在支持HTML的环境(包括不少现代的Markdown编辑器1)使用<ruby>标签为汉字等表意文字添加注音(如拼音振假名),是一个非常实用的功能。然而,一个常见的痛点是,在不支持该标签的纯文本渲染环境下,内容的可读性会大大降低。

例如,一个标准的<ruby>标签:

<ruby>大学<rt>だいがく</rt></ruby>

在纯文本的渲染环境中会显示为大学だいがく,这显然不够理想。2

优雅降级的方案:<rp>标签

HTML标准为此提供了一个优雅的解决方案:<rp>(ruby parenthesis)标签。它的作用是包裹“备用字符”(通常是括号),这些字符只在不支持<ruby>的环境中显示。

理想的格式应该是这样:

<ruby>大学<rp>(</rp><rt>だいがく</rt><rp>)</rp></ruby>

这样可以实现两全其美的效果:

  • 在支持的环境3:正常显示注音样式,括号被隐藏。
  • 在不支持的环境(纯文本):显示为大学(だいがく),未尝有损可读性。

那么,如何将手上的文字(譬如说电子笔记库)中所有旧格式的<ruby>标签批量升级到这种新格式呢?自然会想到的是全局搜索与正则表达式。

第一版方案:简单替换

警告:请不要急着一行行跟着以下方案批量替换,建议先看看下文再做决定。另外,任何时候都请记得做好备份,再批量修改。)

这里用可以直接管理包括.markdown文件在内的笔记文档的VS Code来举例。我们最直接的想法是找到所有的注音标签,然后给它们加上括号。

  • 查找<rt>(.*?)<\/rt>
  • 替换<rp>(</rp><rt>$1</rt><rp>)</rp>

这个方案可以处理最简单的情况。但很快我们就会发现第一个问题。

边界情况:一个词组内的多个注音

当遇到像日语“しん”这样的词,其源代码可能是:

<ruby>地<rt>じ</rt>震<rt>しん</rt></ruby>

上面的简单方案能正确工作吗?是的。它会独立地将<rt>じ</rt>替换为<rp>(</rp><rt>じ</rt><rp>)</rp>,并将<rt>しん</rt>替换为<rp>(</rp><rt>しん</rt><rp>)</rp>,最终得到正确的结果:

<ruby>地<rp>(</rp><rt>じ</rt><rp>)</rp>震<rp>(</rp><rt>しん</rt><rp>)</rp></ruby>

到目前为止,一切似乎都很顺利。但一个更隐蔽的“定时炸弹”埋藏在这个方案中。

第二版方案:解决重复执行的bug

问题在于,如果我们不小心再次运行4这个替换脚本,会发生什么?

它会找到已经修复好的<rp>(</rp><rt>じ</rt><rp>)</rp>中的<rt>じ</rt>,然后再次为它套上括号,导致灾难性的结果:

<rp>(</rp><rp>(</rp><rt>じ</rt><rp>)</rp><rp>)</rp>

这破坏了幂等性5原则。一个健壮的脚本必须能够安全地重复执行而不产生副作用。

因此,我们需要一个最终的、更智能的查找逻辑:只查找那些尚未被<rp>(</rp><rp>)</rp>包裹的<rt>标签。

终极解决方案:使用反向否定查找

正则表达式的“反向否定查找”(negative lookbehind),写作(?<!...),是解决这个问题的完美工具。它允许我们匹配一个模式,但前提是它的前面是某个特定的字符串。

最终的查找与替换规则

  1. 打开VS Code的“在文件中查找和替换”面板 (Ctrl+Shift+HCmd+Shift+H)。
  2. 确保启用正则表达式模式 (点击 .* 图标)。
  3. 在“查找”(Find)输入框中,粘贴以下表达式(?<!<rp>\(<\/rp>)<rt>(.*?)<\/rt>
  4. 在“替换”(Replace)输入框中,粘贴以下内容<rp>(</rp><rt>$1</rt><rp>)</rp>

工作原理解析

  • 查找(?<!<rp>\(<\/rp>)<rt>(.*?)<\/rt>
    • (?<!<rp>\(<\/rp>):这是关键。它是一个反向否定查找,意思是:“从当前位置往前看,前面的文本不能是 <rp>(</rp>”。注意,为了匹配字面上的括号 (,我们用 \( 对其进行了转义。
    • <rt>(.*?)<\/rt>:这部分和之前一样,用于匹配 <rt> 标签及其内容。

这个查找表达式现在变得非常智能:

  • 匹配<ruby>地<rt>じ</rt>...中的<rt>じ</rt>,因为它的前面是字符,不是<rp>(</rp>
  • 不能匹配<ruby>地<rp>(</rp><rt>じ</rt>...中的<rt>じ</rt>,因为它前面的文本正好是我们排除了的<rp>(</rp>

这样,无论对文件执行多少次这个替换操作,它都只会影响那些尚未被修复的旧标签,而对已经符合新格式的标签秋毫无犯,完美地保证了操作的安全性和幂等性6

通过这个逐步优化的过程,我们最终得到了一个强大、安全且一劳永逸的解决方案,可以放心地用它来优化整个笔记库。

尾注

  1. 尽管<ruby>标签并不是标准的Markdown语法——从“<”与“>”就能看出它的XML色彩,但是不少现代的Markdown编辑器——例如Obsidian之类——都会尽量支持HTML语法,<ruby>标签也就包含在内了。 ↩
  2. 偏偏市面上大把网页都是这个样子,吾辈任重道远呐。 ↩
  3. 大到现代浏览器,小到Obsidian之类支援HTML的笔记软件的预览界面。 ↩
  4. 甚至还有种情况,就是——虽然是头一回尝试批量执行,但是待执行的文档里面已经包含有写好了<rp><ruby>标签了。 ↩
  5. 幂等性(idempotence)指的是在一次或多次执行相同操作后,系统的状态保持不变,即无论执行多少次,结果都是相同的。 ↩
  6. 对“幂等性”概念的解释参见前文。 ↩

使用net use命令来临时挂载网络目录

2025-05-02 09:34:00

在Windows CMD中,如果无法直接cd到一个网络目录(专门些的名字叫——通用命名约定〈UNC〉路径),可以使用net use命令来临时挂载网络目录。以下是具体步骤12

  1. 使用net use命令挂载网络目录:
net use Z: \\network_path\shared_folder /user:username password
  • 其中:
    • Z: 是你希望分配给网络目录的本地驱动器号。
    • \\network_path\shared_folder是网络目录的路径。
    • /user:username password是访问网络目录所需的用户名和密码。
    • 挂载完毕后,不仅在CMD内,图形界面的“文件资源管理器”下“此电脑”中也可以看到该挂载目录。
  1. 访问挂载的网络目录:
Z: # 直接输入`Z:`便可切换至该挂载盘符
cd shared_folder # 然后用`cd`命令跳转
  1. 完成操作后卸载网络目录:
net use Z: /delete

补充:pushd命令

在Windows CMD中,pushd命令也可以用来临时挂载网络目录并切换到该目录(而且该方式还更常见一些)。具体步骤如下:

  1. 使用pushd命令挂载网络目录3
set unc_path=\\network_path\shared_folder\b\c
pushd %unc_path%
  1. 执行想要的代码;
  1. 完成操作后使用popd命令卸载网络目录:
popd

使用pushd命令时,它会将网络路径\\network_path\shared_folder挂载到一个可用的盘符(例如Z:),并将工作目录更改为Z:\b\c
但是,这种方法有一个致命的缺点:如果用户对\\network_path\shared_folder\b\c有权限,但对\\network_path\shared_folder没有权限,那么所有在此目录下的命令都会报错:Access is denied4

参考资料

  1. rwv. 在 Windows CMD 中挂载网络路径至本地盘符. rwv 的博客. ↩
  2. Windows掛載共享磁碟/網路磁碟(CIFS)指令. 平凡的幸福. ↩
  3. pushd. Microsoft Learn. ↩
  4. rwv. 在 Windows CMD 中挂载网络路径至本地盘符. rwv 的博客. ↩

进入不断重启的Docker容器的命令行之方法

2024-11-05 10:16:45

停止自动重启

如果容器正在使用docker-compose.yml设置重启策略,临时将restart: always改为restart: no,然后执行docker-compose down停止它。

启动容器进入临时shell

手动启动容器并覆盖其默认命令,以便进入容器并设置权限。运行:

docker run -it --rm --entrypoint /bin/sh your_image_name

退出

做完想做的事后,退出容器命令行:

exit

自建Bookwyrm无法查询远端用户?——开启数据库扩展

2024-10-12 12:01:44

在这篇博文中,笔者(山月)想记录自己如何解决BookWyrm部署过程中遇到的数据库问题,特别是在远程用户搜索时遇到的 “function similarity(character varying, unknown) does not exist” 错误。

背景

背景是笔者(山月)从YunoHost搬迁到现有环境,使用Docker Compose来运行BookWyrm,但在搜索用户时总是出现数据库报错,提示找不到相似度函数。经过查找,了解到这是由于PostgreSQL中缺少pg_trgm扩展导致的。

解法

为了解决这个问题,笔者(山月)进入PostgreSQL数据库,并运行以下命令来安装所需的扩展:

CREATE EXTENSION IF NOT EXISTS pg_trgm;

执行上述命令后,数据库中添加了相应的相似度函数,错误终于得到了修复,用户搜索功能也正常运行了。

总结

看来,有时候问题并不是代码本身,而是数据库的配置。

寄语

希望这篇文章能帮助到遇到类似问题的人,如果你也在使用BookWyrm或其他基于PostgreSQL的应用,记得检查是否已安装所有必要的扩展,尤其是像pg_trgm这样的函数库,它能为用户搜索和文本相似度匹配提供很大的帮助。

BookWyrm无法增添书本、作者、阅读进度……?——解决数据库自增序列问题

2024-10-12 11:28:53

selective focus photography of brown wooden book shelf

引言

最近笔者(山月)将BookWyrm应用从YunoHost迁移到了使用Docker Compose的独立服务器环境,然而在新的环境中遇到了严重的问题:数据库中的表无法正常新增内容,例如无法添加图书、作者,或更新阅读状态等。在调试过程中,每次进行数据迁移操作时,都会遇到数据库主键重复的报错。这篇博文记录了笔者解决这一问题的全过程,希望能够帮助遇到相似困境的朋友们。

问题背景

在将BookWyrm从YunoHost迁移到Docker Compose环境后,笔者(山月)发现新增数据的操作频繁失败,无论是添加图书、作者,还是更新阅读状态,都会遇到数据库报错的问题。具体表现为,当执行Django的migrate命令时,报错显示主键重复(例如 django.db.utils.IntegrityError: duplicate key value violates unique constraint)。

笔者最初的解决方案是手动调整有问题的数据库表的主键自增计数器。但由于涉及的表非常多,一个个手动调整非常低效。这个过程也让笔者意识到,数据库迁移中某些自增序列可能没有同步,导致插入新记录时主键重复。

解决方案:自动校准PostgreSQL自增序列

在多次尝试手动解决主键问题无果后,笔者(山月)决定寻找一种更加自动化的方法,来确保所有数据库表的自增序列都能够同步。笔者最终找到了一个有效的方法:编写一个函数自动校准数据库中所有表的自增序列。

这个函数通过遍历数据库中所有具有自增序列的表,查询每个表的最大主键值,并将自增序列设置为该最大值加一。这样,所有表的自增序列都能够与表中现有数据保持一致,避免了重复主键错误。

下面是这个自动校准函数的实现:

-- 避免重复创建函数
DROP FUNCTION IF EXISTS reset_sequences_for_tables();
-- 重新创建函数
CREATE OR REPLACE FUNCTION reset_sequences_for_tables() RETURNS VOID AS $$
DECLARE
    table_name_text TEXT;
    seq_name TEXT;
    max_id INT;
    default_value TEXT;
    pk_column_name TEXT;
BEGIN
    FOR table_name_text IN
        SELECT t.table_name
        FROM information_schema.tables AS t
        WHERE t.table_schema = 'public'
        AND EXISTS (
            SELECT 1
            FROM information_schema.columns AS c
            WHERE c.table_name = t.table_name
            AND c.column_default ILIKE 'nextval%'
        )
    LOOP
        SELECT column_name INTO pk_column_name
        FROM information_schema.columns AS c
        WHERE c.table_name = table_name_text
        AND c.column_default ILIKE 'nextval%';

        SELECT column_default INTO default_value
        FROM information_schema.columns AS c
        WHERE c.table_name = table_name_text
        AND c.column_name = pk_column_name;

        seq_name := substring(default_value from E'\'(\\w+)\'::regclass');

        IF EXISTS (SELECT 1 FROM pg_class WHERE relname = seq_name) THEN
            EXECUTE 'SELECT MAX(' || pk_column_name || ') FROM ' || table_name_text INTO max_id;

            IF max_id IS NULL THEN
                EXECUTE 'SELECT setval(' || quote_literal(seq_name) || ', 1, false)';
            ELSE
                EXECUTE 'SELECT setval(' || COALESCE(quote_literal(seq_name), 'null') || ', ' || max_id || ')';
            END IF;
        ELSE
            RAISE NOTICE 'Sequence not found for table: %', table_name_text;
        END IF;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

创建函数后,执行它来重置所有自增序列的值:

SELECT reset_sequences_for_tables();

这一步将自动校准所有有自增序列的表的主键序列,让它们与表中的最大ID对应,避免重复主键的情况。

执行结果

执行该函数后,所有表的自增序列都得到了自动校准,数据库主键重复的问题也顺利解决了。执行migrate命令不再报错,BookWyrm的功能恢复正常,现在可以正常添加图书、作者和更新阅读状态。

总结

在迁移BookWyrm应用时,数据库中的自增序列可能因为不同的环境和数据迁移方式而失去同步,导致主键重复的问题。这篇博客记录了如何通过编写一个函数,自动校准PostgreSQL数据库中所有表的自增序列,确保数据一致性并解决问题。

如果你也遇到类似的问题,希望这篇文章能够对你有所帮助。