iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >pt-archiver和自增主键的问题怎么解决
  • 522
分享到

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

2023-06-30 10:06:00 522人浏览 八月长安
摘要

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

今天小编给大家分享一下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" <strong>--no-safe-auto-increment</strong> --dry-runSELECT  `id`,`a` FROM `test`.`tt1` FORCE INDEX(`PRIMARY`) WHERE (1=1) ORDER BY `id` LIMIT 1SELECT  `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  `id`,`a` FROM `test`.`tt1` FORCE INDEX(`PRIMARY`) WHERE (1=1) <strong>AND (`id` < '5009')</strong> ORDER BY `id` LIMIT 1SELECT  `id`,`a` FROM `test`.`tt1` FORCE INDEX(`PRIMARY`) WHERE (1=1) <strong>AND (`id` < '5009')</strong> AND ((`id` > ?)) ORDER BY `id` LIMIT 1INSERT INTO `test`.`tt2`(`id`,`a`) VALUES (?,?)

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

如果服务器重新启动,&ndash;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 时,了解使用 &ndash;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)

使用 &ndash;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 选项的原理和作用 。在我们得出一切都很好的结论之前,让我们多考虑一下选项本身存在的意义。

  • 默认情况下,&ndash;no-delete 操作应包含 &ndash;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和自增主键的问题怎么解决”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网精选频道。

--结束END--

本文标题: pt-archiver和自增主键的问题怎么解决

本文链接: https://www.lsjlt.com/news/328073.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • c语言怎么保证除完还是小数
    在 c 语言中,整数除法只能得到整数结果,要得到小数结果,需将操作数显式转换为浮点数:将一个操作数转换为浮点数,如 float result = num1 / (float)num2;将...
    99+
    2024-05-14
    c语言
  • c语言怎么让结尾不输出空行字符
    要阻止 c 语言程序结尾输出空行字符,可以使用以下方法:将 main 函数的返回值类型改为 void;在 main 函数中显式返回 0;调用 fflush(stdout) 函数刷新标准输...
    99+
    2024-05-14
    c语言
  • c语言怎么让结尾不输出空行数据
    在 c 语言中,可通过以下方法抑制 printf() 函数在程序结束时打印末尾空行:调用 fflush() 函数刷新缓冲区,立即输出所有数据;使用 setvbuf() 函数关闭缓冲,使数...
    99+
    2024-05-14
    c语言
  • c语言怎么让结尾无空行
    在 c 中去除结尾空行的方法:使用 fflush() 刷新缓冲区。使用 setvbuf() 将缓冲模式设置为 _ionbf。使用 printf 宏,它默认禁用缓冲。 如何在 C 语言中...
    99+
    2024-05-14
    c语言
  • c语言怎么输入实数赋值
    c语言中使用scanf()函数输入实数并赋值给变量:格式:scanf("%lf", &amp;variable);%lf是格式说明符,指定输入双精度浮点数;&...
    99+
    2024-05-14
    c语言
  • c语言怎么表达负数
    c语言中,负数以减号 (-) 表示,放在数字或变量前。负数运算规则包括:绝对值取正数;加正数或负数,结果取决于绝对值大小;乘或除以正数或负数,结果由符号奇偶性决定。负数的平方始终为正数,...
    99+
    2024-05-14
    c语言
  • c语言怎么输入Jac数列
    jacobi 数列的输入和生成方法分别有:1. 直接输入法:使用 scanf() 函数逐项输入数列。2. 递归生成法:使用递归公式生成数列,需初始化数列的前两项,然后按公式生成后续项。 ...
    99+
    2024-05-14
    c语言
  • c语言怎么把数组变成字符串
    在 c 语言中,将数组转换成字符串的方法包括:使用 sprintf() 将数组格式化为字符串。使用 strcpy() 将数组复制到字符串。使用 strncpy() 将指定长度的数组复制到...
    99+
    2024-05-14
    c语言
  • c语言怎么批量注释
    批量注释 c 语言代码的方法有:使用代码编辑器:使用快捷键或菜单命令自动添加 // 注释符号。使用注释工具:如 doxygen 和 cutter,批量添加行注释、块注释和文档注释。使用脚...
    99+
    2024-05-14
    python sublime c语言
  • c语言怎么把选中的全部注释
    c语言中注释选中内容可通过以下步骤实现:选中要注释的代码。根据使用的编辑器或ide,执行注释操作,例如在visual studio中右键单击并选择“注释所选内容”。添加注释内容。保存更改...
    99+
    2024-05-14
    sublime c语言
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作