RGJ
(Richard - Communiteq)
2024 年9 月 13 日 17:30
1
我们有一个论坛,其中 user_auth_token_logs 有 6100 万行(并且还在增长)。
只有 25k user_auth_tokens。
在 6100 万行中,有 5400 万行引用了一个不再存在的 user_auth_token(即数据库完整性问题)。在 6100 万行中,大约有 5800 万行比 2 个月大(即似乎无用?)
问题:
我们能否在不冒进一步完整性风险的情况下进行清理?
是否应该有一个作业自动清理此数据?
db=# select count(*) from user_auth_tokens;
count
-------
25648
db=# select count(*) from user_auth_token_logs;
count
----------
61415352
db=# select count(*) from user_auth_token_logs where user_auth_token_id not in (select id from user_auth_tokens);
count
----------
54558442
db=# select count(*) from user_auth_token_logs where created_at < '2024-07-13';
count
----------
58565943
4 个赞
pmusaraj
(Penar Musaraj)
2024 年9 月 13 日 18:22
3
是的,user_auth_token_logs 仅用于调试目的。所有行都可以清空,唯一的后果是您将没有任何日志可供调试。
Richard - Communiteq:
是否可以有一个作业自动清理此内容?
这应该由以下内容覆盖:
https://github.com/discourse/discourse/blob/main/app/jobs/scheduled/weekly.rb#L13
2 个赞
RGJ
(Richard - Communiteq)
2024 年9 月 13 日 19:07
5
谢谢,我之前没意识到这一点。
所以……清理工作仅在 verbose_auth_token_logging 为 true 时运行(在此实例上并非如此)
但是非详细日志记录始终会发生,无论设置如何
根据 8fb823c
将此移至 Bug
4 个赞
pmusaraj
(Penar Musaraj)
2024 年9 月 13 日 19:45
6
你说得对,抓得好。看起来第 214 至 217 行 也需要修复。
我乐于在特定时间后进行全局清理。@osama (因为你是上面链接的提交的作者),你认为我们可以在一段时间后清理所有这些日志吗(如果可以,多久之后)?听起来我们需要保留其中一些日志来检测可疑登录。
4 个赞
RGJ
(Richard - Communiteq)
2024 年9 月 13 日 22:16
7
为什么需要修复? 那段代码是关于清理轮换的 UserAuthToken,而不是关于日志记录?
更新:启用 SiteSetting.verbose_auth_token_logging、触发每周作业并运行 VACUUM FULL user_auth_token_logs 后,该表从 16GB 减小到 687MB
今天拯救了一些树
3 个赞
Osama
2024 年9 月 16 日 20:15
8
是的,我认为我们可以清理大部分日志,但其中一些必须保留。具体来说,我认为任何操作包含 suspicious、generate 或 rotate 的记录都需要保留,因为它们用于检测和生成可疑登录的报告。
title: I18n.t("reports.suspicious_logins.labels.login_time"),
},
]
report.data = []
sql = <<~SQL
SELECT u.id user_id, u.username, u.uploaded_avatar_id, t.client_ip, t.user_agent, t.created_at login_time
FROM user_auth_token_logs t
JOIN users u ON u.id = t.user_id
WHERE t.action = 'suspicious'
AND t.created_at >= :start_date
AND t.created_at <= :end_date
ORDER BY t.created_at DESC
SQL
DB
.query(sql, start_date: report.start_date, end_date: report.end_date)
.each do |row|
data = {}
Math.sin((lat2_rad - lat1_rad) / 2)**2 +
Math.cos(lat1_rad) * Math.cos(lat2_rad) * Math.sin((lon2_rad - lon1_rad) / 2)**2
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
c * EARTH_RADIUS_KM
end
def self.is_suspicious(user_id, user_ip)
return false unless User.find_by(id: user_id)&.staff?
ips = UserAuthTokenLog.where(user_id: user_id).pluck(:client_ip)
ips.delete_at(ips.index(user_ip) || ips.length) # delete one occurrence (current)
ips.uniq!
return false if ips.empty? # first login is never suspicious
if user_location = login_location(user_ip)
ips.none? do |ip|
if location = login_location(ip)
distance(user_location, location) < SiteSetting.max_suspicious_distance_km
end
end
3 个赞
我在论坛上看到这个 bug 从未修复
可疑登录报告似乎仅适用于员工成员,是否有理由为非管理员保留这些日志?
报告才能正常工作,是否需要从账户历史记录开始的数据?日志能否缩短到过去 6 个月?
目前根本没有清理,这存在隐私问题。
2 个赞
RGJ
(Richard - Communiteq)
2025 年8 月 8 日 16:31
13
我也没看懂上面的讨论。
这个 bug 很简单:如果模式不是 verbose,那么 UserAuthTokenLog 就根本不会被清理,永远不会。这个 if 必须去掉。
原始实现只在
SiteSetting.verbose_auth_token_logging 为 true 时记录。这仍然存在一个问题,即禁用它之后,剩余的最新日志会保留,但这只是一个小问题。
但是 这个更改 使日志记录变得无条件(“现在无论 verbose_auth_token_logging 设置如何,都会始终记录 generate、rotate 和 suspicious 身份验证令牌日志 ”)。
TLDR;那个更改忘记了也让移除操作变得无条件。
3 个赞
sam
(Sam Saffron)
2025 年8 月 11 日 02:47
14
当然,我们将在未来几周内解决这个问题。如果您急需,请随时提交一个(经过测试并确认如预期工作的)拉取请求。
1 个赞
RGJ
(Richard - Communiteq)
2025 年8 月 13 日 10:05
17
pmusaraj
(Penar Musaraj)
2025 年8 月 14 日 17:13
20
确实,在 @Osama 的帮助下,该 PR 现已合并。它解决了大多数类型的 user_auth_token_logs,但并非全部,我们将尽快跟进修复 generate 条目。(有关更多背景信息,请参阅上方 PR 链接中的讨论)。
在跟进修复期间,我将保持此主题开放。
4 个赞