在容器中运行的mysql数据库定时备份脚本

单次备份直接跑:

1
docker exec -it mysql容器名/id mysqldump --all-databases -u用户 -p > ./mysql-backup/backup_$(date +%Y%m%d_%H%M).sql

命令行提示输入密码

注意使用--all-databases会连 mysql 本身内部数据库也导出。

批量定时让 AI 写了个脚本,改了几个版本,测试过没啥太大问题。

不过这个版本会把密码留在命令行里,我这里是单独建了个 localhost 能用的密码,不放心可以写临时文件/放环境变量等方法。

会创建当前时间的文件夹,里面按照每个数据库存放对应名字的 sql,设置了过期时间。

这个只能针对比较小的数据库备份,几 G 的无所谓,几十 G 上百 G 的就很慢了(这种业务量还是买云上的数据库吧)。

定时部分直接用 crontab 调这个脚本就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/bin/bash

# =================================================================
# Docker MySQL 数据库备份脚本
# - 为每次备份创建独立的、带时间戳的文件夹
# - 备份为纯 .sql 文件,不压缩
# - 仅在所有备份成功后,才清理旧的备份文件夹
# - 清理前,在日志中一次性记录所有将被删除的目录列表
# =================================================================

# --- 自定义配置 ---

# MySQL 容器名称
CONTAINER_NAME="your_mysql_container_name"

# MySQL 用户名 (推荐使用下面创建的 'backup' 用户)
MYSQL_USER="backup"

# MySQL 密码 (您为 'backup' 用户设置的密码)
MYSQL_PASSWORD="your_strong_password_here"

# 需要备份的数据库列表,多个数据库用空格隔开
# 例如: "db1 db2 db3"
DATABASE_NAMES="your_db_name1 your_db_name2"

# 备份文件存放的根目录
BACKUP_ROOT_DIR="/data/mysql_backups"

# 备份文件保留天数
RETENTION_DAYS=30

# 日志文件路径
LOG_FILE="${BACKUP_ROOT_DIR}/backup.log"

# --- 脚本主体 ---

# 1. 创建本次备份的专属文件夹
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
CURRENT_BACKUP_DIR="${BACKUP_ROOT_DIR}/${TIMESTAMP}"
mkdir -p ${CURRENT_BACKUP_DIR}

# --- 函数定义 ---
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> ${LOG_FILE}
}

# 2. 执行备份
log "开始备份任务,备份至目录: ${CURRENT_BACKUP_DIR}"
if [ -z "${DATABASE_NAMES}" ]; then
log "错误: 没有指定要备份的数据库 (DATABASE_NAMES 为空)。"
exit 1
fi

ALL_BACKUPS_SUCCEEDED=true
for DB_NAME in ${DATABASE_NAMES}
do
log "正在备份数据库: ${DB_NAME}"
BACKUP_FILE="${CURRENT_BACKUP_DIR}/${DB_NAME}.sql"
docker exec ${CONTAINER_NAME} /usr/bin/mysqldump -u${MYSQL_USER} -p${MYSQL_PASSWORD} --databases ${DB_NAME} --single-transaction > ${BACKUP_FILE}
if [ $? -eq 0 ]; then
log "数据库 ${DB_NAME} 备份成功, 文件: ${BACKUP_FILE}"
else
log "错误: 数据库 ${DB_NAME} 备份失败。"
ALL_BACKUPS_SUCCEEDED=false
rm -f ${BACKUP_FILE}
fi
done
log "所有数据库备份操作执行完毕"

# 3. 清理旧备份 (仅在所有备份都成功时执行)
if [ "${ALL_BACKUPS_SUCCEEDED}" = true ]; then
log "本次所有备份任务均成功,开始清理 ${RETENTION_DAYS} 天前的旧备份文件夹"

# --- 这里是修改的核心部分 ---
# 先找到所有要删除的目录,存入变量
DIRS_TO_DELETE=$(find ${BACKUP_ROOT_DIR} -type d -name "20[0-9][0-9]*_*" -mtime +${RETENTION_DAYS})

if [ -n "${DIRS_TO_DELETE}" ]; then
# 如果找到了需要删除的目录,则先记录日志,然后执行删除
log "将要删除以下旧备份目录:"
log "${DIRS_TO_DELETE}"
# 使用 xargs 来处理目录列表并删除
echo "${DIRS_TO_DELETE}" | xargs rm -rf
log "旧备份文件夹清理完成"
else
# 如果没有找到,也记录一下
log "没有找到需要清理的旧备份目录。"
fi
else
log "警告: 本次备份任务中存在失败项,将跳过清理旧备份的操作以确保数据安全。"
log "由于备份失败,本次创建的文件夹 ${CURRENT_BACKUP_DIR} 可能包含不完整的备份。"
fi

log "=========================================================="

timestamp存取差几小时? mysql timestamp的timezone问题以及如何在mysql2设置

在 Node.js 应用中使用 MySQL 时,时间戳(TIMESTAMP)字段出现的“8 小时差异”是一个经典难题。这个问题的根源并非单一因素,而是由 MySQL 自身的时区机制、mysql2 驱动的特定行为,以及一个极具迷惑性的默认配置共同造成的。

本文将澄清 MySQL TIMESTAMP 的存储与转换原理,并深入剖析 mysql2 驱动中 timezone 配置项的真正含义及其默认值'local'所带来的陷阱,最终提供两套清晰的最佳实践方案。

Read More

drizzle如何处理mysql的bit类型

mysql 的 boolean 类型其实是 tinyint(1)的别名,一些 ORM 工具无法识别把他识别到对应语言的 boolean 类型,日常实践有时候会选择用bit(1)这个类型,比如javaJOOQ,boolean 类型会变为 java 的Byte,而bit(1)则是 java 的Boolean

但是 drizzle 的 mysql 内置类型中没有bit(1)。你用他的drizzle-kit pull之后会返回这个结果:

1
2
// Warning: Can't parse bit(1) from database
// bit(1)Type: bit(1)("deleted").notNull(),

但是如果是已经建好的表,其他逻辑在用的话,把bit(1)改成boolean并不方便。

需要我们自己定义一个类型。

bit(1)这个类型不同驱动返回不同,有些可能是作为整数,有些可能是作为 Buffer。所以扩展一下就行:

Read More

Next.js 如何在客户端导航时获取上一页(referer)

想给之前上线的工具站做个博客数据统计: blogs

理所当然用到了document.referer,最方便的获取上一个页面的方式,结果发现获取到的都是第一次 load 的页面,而不是导航前的那个页面。

为什么会这样?

Next.js 在生产环境中默认采用前端导航(Client-side Navigation)的方式。这意味着页面加载完之后,在网站内部点击链接时,浏览器并不会执行一次完整的页面刷新。相反,Next.js 会在客户端通过 JavaScript 异步加载新页面的数据和组件,然后更新 DOM。

这种类似 单页应用(SPA) 的行为导致了一个关键问题:
document.referrer 的值在页面首次加载后保持不变。当通过内部链接从blog/zh/1导航到 blog/zh/post/[slug] 时,由于没有发生完整的页面重载,document.referrer 的值仍然会是最初访问网站的那个值,而不是blog/zh/1

Read More

Next.js RSC _rsc参数丢失的那些坑以及解决方案

最近在用 Next.js 的 RSC(React Server Component)时遇到了一个比较隐晦的问题,记录一下踩坑过程和应对方案。

如果你在项目里既使用了 CDN(并且缓存了 html),又使用了middleware的重定向(middleware 会处理 rsc 请求),又用了 RSC 特性(开启了 prefetch 等情况),如果你发现部分页面 html 变成了一大串“乱码”(其实是 rsc 请求的返回结果),可以仔细看看。

RSC 请求是怎么工作的?

Next.js 在请求 RSC 和 HTML 页面时,路径和方法其实是一样的,唯一的区别在于它会带上一个 _rsc 的参数和一些特定 header。

比如你访问页面 /about

  • HTML 请求
    GET /about
  • RSC 请求
    GET /about?_rsc=<随机字符串> 以及特定的 header

这里的 _rsc 参数是 Next.js 内部用来标识“这是一次 RSC 请求”,header 里也有类似 Next-Router-State-Tree, rsc 等用于数据请求和分割的内容。

Read More

[翻译]我如何使用 Claude Code

原文出处: https://spiess.dev/blog/how-i-use-claude-code

一个月前,我订阅了 Claude Max。在此之前,我已经使用包括 Claude Code 在内的 AI 代理一段时间了,但随着统一价格的推出,我的使用量猛增,它已成为我许多任务的日常驱动力。我发现自己现在去 VS Code 的次数少了很多。

由于 AI 代理目前对每个人来说都是新事物,我想分享一些我最近注意到模式可能会很有趣。以下是我如何使用 Claude code。

开始新对话 (Start New Threads)

如果说我希望你从这篇文章中学到一件事,那就是你应该更频繁地调用 /clear

AI 代理往往随着对话时间的延长而变得更不可预测。当你提出不同问题时尤其如此。我发现即使这意味着重复一些指令,创建一个新的提示通常会更有效。

一旦我开始更积极地这样做,我的结果就显著改善了。而且我绝对不是唯一一个提出这个建议的人。

Read More

Next.js使用auth.js+dirzzle+postgresql报错分析

在自己的测试项目里想着做登录功能,看到authjs就接到项目里去,本身就使用的drizzle,在不配置 db adapter 的情况下运行正常,但只要配置就会报错:

1
2
3
4
5
6
7
8
⨯ Error [TypeError]: Cannot read properties of undefined (reading 'reduce')
at <unknown> (.next\server\edge\chunks\edge-wrapper_c7ecd8c0.js:709:27)
at runModuleExecutionHooks (.next\server\edge\chunks\edge-wrapper_c7ecd8c0.js:755:9)
at instantiateModule (.next\server\edge\chunks\edge-wrapper_c7ecd8c0.js:707:9)
at getOrInstantiateModuleFromParent (.next\server\edge\chunks\edge-wrapper_c7ecd8c0.js:640:12)
at esmImport (.next\server\edge\chunks\edge-wrapper_c7ecd8c0.js:143:20)
at [project]/src/db/db.ts [middleware-edge] (ecmascript) (.next\server\edge\chunks\[root of the server]__a687996d._.js:28:218)
at <unknown> (.next\server\edge\chunks\edge-wrapper_c7ecd8c0.js:709:27)

无法启动

Read More

显卡的TOPS AI算力比较

虽然自己没设备但喜欢聊 😀,和别人讨论的时候经常要反复查,查询一下汇总,有可能填错了。。。到时候发现错误再订正吧。

AMD 的没找到哪个表/文档里有算 TOPS 的…就不列了

N 卡

20 系到 40 系

GeForce RTX 20 系列

型号 架构 制程 (nm) 显存大小 显存类型 显存位宽 显存带宽 (GB/s) 峰值单精度 (FP32) TOPS (AI) TDP (W)
RTX 2080 Ti Turing 12 11GB GDDR6 352-bit 616 13.45 TFLOPS 114 TOPS 260
RTX 2080 Super Turing 12 8GB GDDR6 256-bit 496 11.15 TFLOPS 89 TOPS 250
RTX 2080 Turing 12 8GB GDDR6 256-bit 448 10.07 TFLOPS 81 TOPS 225
RTX 2070 Super Turing 12 8GB GDDR6 256-bit 448 9.06 TFLOPS 72 TOPS 215
RTX 2070 Turing 12 8GB GDDR6 256-bit 448 7.47 TFLOPS 65 TOPS 175
RTX 2060 Super Turing 12 8GB GDDR6 256-bit 448 7.19 TFLOPS 57 TOPS 175
RTX 2060 Turing 12 6GB GDDR6 192-bit 336 6.45 TFLOPS 52 TOPS 160

Read More

Jina ReaderLM v2 测试记录

jina 出了 ReaderLM v2 版本,这个版本的 ReaderLM 在处理文本数据时更加高效和准确。
之前简单测试了下 v1, 结论是:

  • 幻觉严重, 尤其特别喜欢造 url
  • 很容易触发无限生成 比如 example1 example2…. 一直生成下去

第一眼就是不可用就没继续了。
这次 v2 来了,测试了一下,幻觉问题好了很多,无限生成测试了几个也没遇到,但最为一个 html 转 markdown 的工具还是不够稳定。
这里的稳定性主要是指,与传统的基于语法树解析的工具相比,它在处理速度和结构识别的准确性上还有差距。他的确能生成不错的 markdown,但是很容易被正确结构但是内容文本里有特殊构造的/或者有一些语法错误的 html 页面所影响。

注意:这个博客里的测试只是为了列出 v2 的一些问题,针对问题进行特殊构造的测试,实际网页可能也遇不到文中提到的问题,具体以实际场景为准了。
顺道一提,这个模型是以 CC 协议发布的,所以商用场景需要遵守相关协议。

Read More