前几天一直都在折腾Memos,原因就是我的Docker容器是利用《如何优雅的一键升级宝塔面板多个Docker容器》的watchtower项目,通过计划任务每周定时检测Docker版本并完成自动更新。所以我的所有Docker版本都是一直保持着最新。也就是这点,违背了“求稳不求新”的原则,导致出现了一些问题。最为严重是Memos,作者更新很随意导致新版本的数据库结构、API接口都发生了改变,与目前使用的“哔哔点啥”的memos页面出现不兼容。
国庆节前,折腾把《完美解决Memos页评论与博客哔哔页面评论互不显示问题。》的问题解决了,方法就是备份数据库文件后直接删除新版Memos容器,安装Memos0.18.2版老板容器,并恢复数据库文件。安装后并没有经过大久测试,结果新的问题出现了。降级后Memos不能发布内容了,乖乖,这可是个大问题。
经过分析,不能发布内容的原因就是新老版本的Memos的数据库结构发生了改变,那么解决的思路也就是把新版数据库数据结构修改为与memos0.18.2保持一致即可。
备份数据库、删除新版安装memos0.18.2版
我在《无需代码,宝塔面板Docker部署便签工具Memos》提到过,当初我们在部署Memos时,已经把Docker内的数据库文件memos_prod.db映射到服务器上,找到新版数据库文件下载到本地后,可以另存为其他名称后删除最新版本memos容器。这次我是直接使用代码安装的0.18.2版,代码如下:
docker run -d --init --name memos --publish 5230:5230 --volume /docker-data/memos/:/var/opt/memos ghcr.io/usememos/memos:0.18.2
利用Navicat Premium工具导出-修改-导入数据库文件
安装好0.18.2版之后,到/docker-data/memos/下同样把memos_prod.db文件下载到本地。
这个时候我们请出今天的主角,Navicat Premium,直接到官网下载即可,14天的试用时间,完全够你折腾了。利用Navicat Premium同时连接打开新、老数据库文件。
经过比较你就会发现新版数据库文件中表名为memo的字段比0.18.2版本多一列uid字段。第一思路就是在新版表memo的uid字段上直接右键点删除,结果报错,只能另寻思路,如果这一步哪位大神有什么方法,一定要分享出来,因为正面我的方法比较繁琐。
那简单方法行不通,只能通过繁琐的方法了,把数据库表的内容导出成可编辑的文件,在相应软件里把memos的uid字段删除后再导入0.18.2版的数据库。具体方法如下:
选中新版数据库memo表,选择工具-导出,这里我选择的是excel数据表(*.xls),导出后用ecxel打开你导出的表格,直接把uid这一列删除即可。注意,这个时候我们再连接0.18.2数据库的memo表,再选择工具导入,注意一定要选对文件类型把修改后的excel文件导入。这个时候,我们就完美地把memo这个表导入了。
其他表的内容按上步方法导出-修改-导入,其实也就是memo和表resource两个表需要删除uid字段,其他像标签、用户、用户设置、系统设置等表只需要把内容导出成excel文件后再直接导到0.18.2的数据库即可。这样就完成了所有的数据迁移工作。
停止容器,恢复数据,完美降级
在服务器上把Memos这个容器先停止,把0.18.2版数据库文件上传到你映射的目录,覆盖旧文件即可。再重新启动容器,OK,十分完美地把Memos0.22.2降到Memos0.18.2版。
经过这一周多时间的测试,再无任何问题,Memos降级完美完成!
发现张老师做事的思路非常明确,确保万无一失
@段先森: 对的呀,必须防范于未然嘛。
老张,我更换了网址 https://www.luosir.cn
@老罗: 罗sir好,我的zhangsir.com被我抛弃了。
张叔这个方法好啊,想起我之前一点点写逆向 SQL,累得够呛。
@Chlorine: 因为不会代码,所以只能想到最为笨的方法。虽然麻烦了点,但是也还是解决了。
Memos 我用了一年多,期间搞过多次 breaking change,有些时候第三方 APP(MoeMemos)和浏览器扩展更新稍慢,未来得及兼容新版本的 Memos,以及 Memos 本身新版本的问题,导致了许多不便。后来我打定主意锁定在一个版本,如非必要就不更新了。
这里 Memos 的数据库最好定期备份一下,用 SQLite 的话直接备份文件也不麻烦。
另外,Memos 在跨版本升级数据库的时候,是有编排 SQL 的(https://github.com/usememos/memos/tree/main/store/migration/sqlite/prod),如果升级变更数据库的路径上只有表结构变更的操作,且没有删除数据的操作,可以反推得到降级的 SQL(应该可以用 GPT 协助编写)并执行,实现无损降级。
(但很不幸有一次我想降级版本的时候恰巧无法无损降级,升级的时候有一个表的字段直接被删除,无法恢复)
@电脑星人: 现在,很多用memos的伙伴们都选择不升级,目前还有人用0.14.X的呢。不过听说0.18.X最为稳定,所以我就降到了0.18.1了。
Docker我一般都是求稳不求新
@萧瑟: 主要是之前我用了自动更新功能,把所有的Docker都保持了最新版本,才导致出现了不少问题。
我的memos版本还停留在0.17.0,够用好用就OK了,不去折腾了。
@落落vici: 能稳定运行就行,现在我也不求新了,求稳。
memo是绝对不升级的,升级改了一大把东西,老版本足以了,我是自己单独弄了一个内嵌的页面
@klcdm: 是的,我现在停留在0.18.1上,
技术流。
@obaby: 都是瞎折腾,没有你“代码流”厉害!
Memos这玩意是绝对不更新的,完全是个人自用项目的形状,功能说删就删,API刷刷改,数据库结构直接做不兼容升级。
@秋风于渭水: 是的,选一个稳定的版本算了,不能升。
折腾也得有技术,话说memos更新这么玄学吗。
@粽叶加米: 是的,更新后会有很多问题。
你这假期也不闲着呀 😂
@Liudon: 都是在折腾memos了。
感觉memos加载还是有点慢
@满心: 慢的原因应该是CDN吧。
虽然我平时不用 Memos,但是我的 Demo 站实时保持更新最新版,也没什么问题。
@大大的小蜗牛: 你是技术牛呀!
memos 的api设计真的是很糟糕。
@keyle: 关键是他升级后会乱改!
每次动memos我都要人工确认一下数据库文件,太不稳定了,生怕搞丢
@肖寒武: 每天做好备份就好了,不怕丢。
同感,不过我不是搞接口开发,只是要和其他自建应用保持相同域名,把memos放在base url下面,用caddy的response replace插件做的,也是升级个版本就各种替换要变化,现在是固定在0.19.0不动了。
我试着直接操纵了一下 `memos_prod.db`,的确报错了。应该是 `uid` 那一列存在一个唯一约束,而 SQLite 在处理带唯一约束的列的时候行为非常抽象,不能直接删除。
@Chlorine: 严格来说,是不能直接删除任何列。
@Chlorine: 老版本数据库没有这一列,从新版降到老版后,这一列就需要删掉了,删了之后才和老版本数据库结构一致!
如果不删,就按我的方法,把新版数据库里数据导出导入到老版本数据库里即可。
@老张: 我写了个脚本,把那两张表其余的列复制出来就可以了。现在也加入 18 版本养老大军了。
想看看有没有什么替代品,感觉这个项目已经让我失望太多次了。
@Chlorine: 是什么脚本?可以分享下嘛!我是代码小白,新旧数据库我是全手动复制的!
@老张: 我这边大概用的是这个:https://gist.dusays.com/chlorine/9c7b71ab8e094ce286ce924b993c9014,直接改原本的数据库会有问题,就新建了一个空白的。如果是其他表的话,需要根据表的结构改一下表名和列数。
但是我的情况特殊,因为没几条 memos,资源文件也非常少,设置也几乎是空的,所以我记得我没费劲琢磨通用方案,直接把 `id` 列重编码之后改了一下 resource 表的内容,设置就直接丢弃了。所以这个脚本肯定没有普适性,希望能有点用……
@Chlorine: 不过手动复制也还好,表不多、结构也不复杂,即使手动导出导入,也十几分钟就可以搞定。
@Chlorine: 从高版本降到低版,那个就要那一例就要删掉,
张老师,这条安装命令运行后显示Unable to find image ‘ghcr.io/usememos/memos:0.18.2’ locally,怎么办呀?
@Mr.He: 没有问题呀,正常的呀!
刚看到,之前没有安装过,那怎么下载老版本啊,直接第一个代码吗,宝塔面板上的不用部署了吗,求
@piter: 是的,直接那一行代码就可以了!