千家信息网

pt-archiver和自增主键的问题怎么解决

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,今天小编给大家分享一下pt-archiver和自增主键的问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收
千家信息网最后更新 2026年11月01日pt-archiver和自增主键的问题怎么解决

今天小编给大家分享一下pt-archiver和自增主键的问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

前言

pt-archiver 是一款常见的 表清理或者归档工具。

MySQL 中删除大表之前可以使用 pt-archiver 批量删除所有记录。这样助于避免在某些情况下您的服务器可能会意外的情况,比如磁盘 IO 满导致数据库hang或者影响正常 SQL 慢查。

问题 "使用 pt-archiver 删除数据时,最后一行数据未被删除。这个是不是bug?"

分析

在解决客户的问题之前,我们需要解释为什么在删除大表之前使用 pt-archiver 当我们在 MySQL 中删除一个表时, MySQL 系统会做如下动作:

删除表数据/索引 (ibd) 和定义 (frm) 文件。
删除触发器。
通过删除要删除的表来更新表定义缓存。
扫描 InnoDB 缓冲池以查找关联页面以使其无效。--内存到的表会遇到系统hang。

需要注意的是,DROP 是一个 DDL 语句,它需要持有元数据锁 (MDL) 才能完成,这样会导致所有其他线程必须等待DDL完成,清除表相关的大量数据页会对缓冲池产生额外的压力。

最后,table_definition_cache 操作需要 LOCK_open mutex 来清理,这会导致所有其他线程等待直到删除完成。

为了降低此操作的严重性,我们可以使用 pt-archiver 通过批量的形式删除大量数据,从而显着降低表大小。一旦我们从大表中删除了记录,DROP 操作就会快速进行而不会对系统性能产生影响。

社区成员注意到此行为,在 pt-archiver 完成后,该表仍有一行待处理。

# Created tablemysql> CREATE TABLE `tt1` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `a` char(5) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB# Poured random test data into itmysql> call populate('test','att1',10000,'N');# Purged data using pt-archiver[root@centos_2 ~]# pt-archiver --source=h=localhost,D=test,t=tt1 --purge --where "1=1"# Verifying count (expected 0, got 1)mysql> select count(*) from test.tt1;+----------+| count(*) |+----------+|        1 |+----------+1 row in set (0.00 sec)

当我们使用带有 --no-delete 参数的 pt-archiver 进行数据归档时,也会发生同样的情况。我们的工具 pt-archiver 似乎没有将最大值复制到目标表。

将表从 tt1 迁移到 tt2 [root@centos_2 ~]# pt-archiver --source=h=localhost,D=test,t=tt1 --dest=h=localhost,D=test,t=tt2 --no-delete --where "1=1"mysql> select count(*) from tt2;+----------+| count(*) |+----------+|     5008 |+----------+1 row in set (0.00 sec)mysql> select count(*) from tt1;+----------+| count(*) |+----------+|     5009 |+----------+1 row in set (0.00 sec)

解析

通读 pt-archiver 文档,有一个选项 –[no]safe-auto-increment 描述了用法:"不要使用 max AUTO_INCREMENT 归档行。"

这意味着,选项 –safe-auto-increment(默认)添加了一个额外的 WHERE 子句,以防止 pt-archiver 在提升单列 AUTO_INCREMENT 时删除最新的行,如下面的代码部分所示:

https://github.com/percona/percona-toolkit/blob/3.x/bin/pt-archiver#L6449   if ( $o->get('safe-auto-increment')         && $sel_stmt->{index}         && scalar(@{$src->{info}->{keys}->{$sel_stmt->{index}}->{cols}}) == 1         && $src->{info}->{is_autoinc}->{            $src->{info}->{keys}->{$sel_stmt->{index}}->{cols}->[0]         }   ) {      my $col = $q->quote($sel_stmt->{scols}->[0]);      my ($val) = $dbh->selectrow_array("SELECT MAX($col) FROM $src->{db_tbl}");      $first_sql .= " AND ($col < " . $q->quote_val($val) . ")";   }

让我们通过空运行输出看看这两个命令之间的区别:

# With --no-safe-auto-increment[root@centos_2 ~]# pt-archiver --source=h=localhost,D=test,t=tt1 --dest=h=localhost,D=test,t=tt2 --no-delete --where "1=1" --no-safe-auto-increment --dry-runSELECT /*!40001 SQL_NO_CACHE */ `id`,`a` FROM `test`.`tt1` FORCE INDEX(`PRIMARY`) WHERE (1=1) ORDER BY `id` LIMIT 1SELECT /*!40001 SQL_NO_CACHE */ `id`,`a` FROM `test`.`tt1` FORCE INDEX(`PRIMARY`) WHERE (1=1) AND ((`id` > ?)) ORDER BY `id` LIMIT 1INSERT INTO `test`.`tt2`(`id`,`a`) VALUES (?,?)
# Without --no-safe-auto-increment (default)[root@centos_2 ~]# pt-archiver --source=h=localhost,D=test,t=tt1 --dest=h=localhost,D=test,t=tt2 --no-delete --where "1=1" --dry-runSELECT /*!40001 SQL_NO_CACHE */ `id`,`a` FROM `test`.`tt1` FORCE INDEX(`PRIMARY`) WHERE (1=1) AND (`id` < '5009') ORDER BY `id` LIMIT 1SELECT /*!40001 SQL_NO_CACHE */ `id`,`a` FROM `test`.`tt1` FORCE INDEX(`PRIMARY`) WHERE (1=1) AND (`id` < '5009') AND ((`id` > ?)) ORDER BY `id` LIMIT 1INSERT INTO `test`.`tt2`(`id`,`a`) VALUES (?,?)

注意到上面的附加子句 "AND ( id< '5009')" 了吗?

如果服务器重新启动,–no-safe-auto-increment 的这个选项可以防止重新使用 AUTO_INCREMENT 值。请注意,额外的 WHERE 子句包含自归档或清除作业开始时自增列的最大值。如果在 pt-archiver 运行时插入新行,pt-archiver 将看不到它们。

好吧,现在我们知道了为什么没有删除干净的"原因",但为什么呢?AUTO_INCREMENT 的安全问题是什么?

AUTO_INCREMENT 计数器存储在内存中,当 MySQL 8.0之前的版本 重新启动(崩溃或其他)时,计数器将重置为最大值。如果发生这种情况并且表正在接受写入,则 AUTO_INCREMENT 值将更改。

# deleting everything from tablemysql> delete from tt1;...mysql> show table status like 'tt1'\G*************************** 1. row ***************************           Name: tt1         Engine: InnoDB... Auto_increment: 10019...# Restarting MySQL[root@centos_2 ~]# systemctl restart mysql# Verifying auto-increment counter[root@centos_2 ~]# mysql test -e "show table status like 'tt1'\G"*************************** 1. row ***************************           Name: tt1         Engine: InnoDB... Auto_increment: 1...

上面的测试结果告诉我们: 这里的问题实际上并不在于 pt-archiver,而在于参数选项。在处理 AUTO_INCREMENT 列时使用 pt-archiver 时,了解使用 –no-safe-auto-increment 选项很重要。

让我们用我们的实验室数据来验证它。

# Verifying the usage of -no-safe-auto-increment option[root@centos_2 ~]# pt-archiver --source=h=localhost,D=test,t=tt1 --purge --where "1=1" --no-safe-auto-incrementmysql> select count(*) from test.tt1;+----------+| count(*) |+----------+|        0 |+----------+1 row in set (0.00 sec)

使用 –no-delete 选项的复制操作也是如此。

[root@centos_2 ~]# pt-archiver --source=h=localhost,D=test,t=tt1 --dest=h=localhost,D=test,t=tt2 --no-delete --where "1=1" --no-safe-auto-incrementmysql> select count(*) from tt1; select count(*) from tt2;+----------+| count(*) |+----------+|     5009 |+----------+1 row in set (0.00 sec)+----------+| count(*) |+----------+|     5009 |+----------+1 row in set (0.00 sec)

通过上面的代码和实际测试,我们知道了 pt-archiver 的 -[no]safe-auto-increment 选项的原理和作用 。在我们得出一切都很好的结论之前,让我们多考虑一下选项本身存在的意义。

  • 默认情况下,–no-delete 操作应包含 –no-safe-auto-increment 选项。目前,safe-auto-increment 是默认行为。当我们使用 pt-archiver 的 --no-delete 选项时,没有删除操作。这意味着 safe-auto-increment 不应成为关注的原因。

  • 对于 MySQL 8.0,不需要 safe-auto-increment 选项。因为 MySQL 8.0 开始,自增的值是持久化的,并且在实例重新启动或崩溃后自增的最大值不变。

而且由于 MySQL 8.0 auto-increment 是通过重做日志持久化的,这使得它们成为pt-archiver 不关心的一个原因。因此,我们根本不需要 safe-auto-increment 选项。

以上就是"pt-archiver和自增主键的问题怎么解决"这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注行业资讯频道。

数据 问题 情况 面的 最大 最大值 知识 篇文章 原因 子句 系统 一行 代码 内存 内容 参数 实际 工具 意味 服务器 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 江苏根荣互联网科技 互联网科技英文 互联网 科技创业 互联网科技公司官网 紫鲸互联网科技 百单互联网科技有限公司 壕鑫互联网络科技 伴你行互联网科技有限公司 猫创互联网科技 金融科技和互联网金融 华中科技有哪些互联网大佬 中国科技互联网公司收入 如何创新互联网科技 佛山市拉法互联网科技有限公司 国大互联网教育科技有限公司薪资 沐思想互联网科技有限公司 中国互联网有什么科技 广州三三互联网科技有限公司 互联网企业和网络科技有限公司 恒生科技互联网指数十大成分股 互联网女皇 腾讯科技 北京禾田雨橡互联网科技 青岛中康互联网医疗科技有限公司 坤平互联网科技 明优互联网科技有限公司 山东子淼互联网科技有限公司 上海创道互联网络科技有限公司 互联网科技接地气 互联网科技手机排行榜 中国科技和美国互联网
0