![紧急!关键 mysql 生产数据库的更新声明现已运行 18 小时,需要帮助](https://linux22.com/image/507109/%E7%B4%A7%E6%80%A5%EF%BC%81%E5%85%B3%E9%94%AE%20mysql%20%E7%94%9F%E4%BA%A7%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E6%9B%B4%E6%96%B0%E5%A3%B0%E6%98%8E%E7%8E%B0%E5%B7%B2%E8%BF%90%E8%A1%8C%2018%20%E5%B0%8F%E6%97%B6%EF%BC%8C%E9%9C%80%E8%A6%81%E5%B8%AE%E5%8A%A9.png)
我们有一张包含 5 亿行的表。不幸的是,其中一列是 int(11),这是一个有符号的 int,它是一个递增值,刚好超过了 21 亿这个神奇数字。这立即导致大约 10,000 名用户停机。我们讨论了许多解决方案,并决定我们可以安全地回滚这个值,比如说 10 亿。但我们必须对每一行都进行回滚。
以下是我们所做的:
更新表 1 设置 MessageId = case when MessageId < 1073741824 then 0 else MessageId - 1073741824 end;
我在一个包含 1000 万行数据的表上测试了此操作,耗时 11 分钟。因此我假设更大的表将耗时 550 分钟,即 9 小时。这将是我们 3 年来最长的停机时间。(我们是一家初创公司)。现在已经持续了 18 个小时。
我们应该做什么?
请不要说我们应该做什么。我认为我们应该一次更新几百万行。
有没有办法查看进度?Mysql 可能挂了?使用 mysql 5.0.22。
谢谢!
答案1
尝试查看 SHOW PROCESSLIST 的输出;它应该可以让您简要了解该线程内部发生的情况;最坏的情况是,您可以终止该线程(使用 KILL $threadID),然后手动清理。
嗨嗨。
答案2
您的意思是:更新 Table1 设置 MessageId = case when MessageId < 1073741824 then消息ID否则 MessageId - 1073741824 结束;
否则我会看到一堆具有相同 ID 的消息。
在 SQL 级别,其他方法可能更快:
create table new_table as
select (all other fields),
case msg id > xxx then msg_id - 1000000 else msg_id
from old_table;
这样,您就可以完全扫描一个表并一次性写入另一个表,而不是进行大量随机 i/o(您可以使用 iostat 检查)。