这个问题
我最近做的一个客户接触的客户需要档案大量来自不同表的行到另一个服务器(在本例中为简单起见我只是归档结果到一个文件中)。
在解释另一个博客。”<一个href="//m.doggingzone.com/blog/2013/08/12/want-to-archive-tables-use-pt-archiver/">想要存档表吗?使用Pe雷竞技下载官网rcona工具包pt-archiver一个>”,您可以使用pt-archiver清洗/档案行从表相匹配”,“任何条件,但这种情况下不容易存档/删除条件复杂,涉及加入许多表…
存档条件涉及与以下四个表查询和下面的表模式。在这个例子中,没有外键,但这种方法也可以使用外键,重新排序表存档/清洗。

和删除条件如下:
|
1
2
3
4
5
6
|
删除
表1
,
表二
,
table3
,
table4
从
表1
内心的
加入
table3
在
表1
.id
=
table3
.table1_id
内心的
加入
表二
在
表1
.table2_id
=
表二
.id
内心的
加入
table4
在
(
table3
.table4_id
=
table4
.id
和
table4
.cond
=
“Value1”
)
在哪里
表1
.created_at
<
“2020-01-01”就是
;
|
可以看出,一个行存档,这取决于其他行表的存在和条件。试图清洗/存档一次一个表不是一个可能的解决方案,因为一旦一行已经清除/存档,这是不可能找到引用的其他行需要清除/一起存档。
所以,在这种情况下我们如何继续?
解决方案
为解决上述问题,最好是建立一个临时表的行包含所有对清除/存档,即:
|
1
2
3
4
5
6
7
8
9
|
mysql
>
选择
*
从
tmp_ids_to_remove
;
+ - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - +
|
table1_id
|
table2_id
|
table3_id
|
table4_id
|
+ - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - +
|
1
|
1
|
1
|
1
|
|
1
|
1
|
2
|
1
|
|
1
|
1
|
3
|
1
|
|
3
|
3
|
5
|
3
|
+ - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - +
|
在上面的例子中,从每个表下面的行必须被净化:
- 表1:id = {1,3}
- 表二:id = {1,3}
- Table3: id = {1, 2, 3, 5}
- Table4: id = {1,3}
然后pt-archiver从<一个href="//m.doggingzone.com/software/database-tools/percona-toolkit">雷竞技下载官网Percona工具包一个>可以用来清洗/存档一次一个表,检查行上清除确实存在“tmp_ids_to_remove”。pt-archiver表达式类似于:
|
1
|
- - -在哪里
的存在(从percona选择tableX_id。雷竞技下载官网tmp_ids_to_removepurge_t WHERE id=purge_t.tableX_id)'
|
和填充表的查询应该类似插入tmp_ids_to_remove(选择<查询>删除条件)即:
|
1
2
3
4
5
6
|
插入
成
雷竞技下载官网
.tmp_ids_to_remove
(
选择
表1
.id
,
表二
.id
,
table3
.id
,
table4
.id
从
表1
内心的
加入
table3
在
表1
.id
=
table3
.table1_id
内心的
加入
表二
在
表1
.table2_id
=
表二
.id
内心的
加入
table4
在
(
table3
.table4_id
=
table4
.id
和
table4
.cond
=
“Value1”
)
在哪里
表1
.created_at
<
“2020-01-01”就是
)
;
|
事情要考虑:
- 而不是创建一个包含所有的“大”表行,可以创建多个小表。简单和更简单的数据视图,一个大桌子在这个例子。
- 上面的插入可能锁定的行可以影响服务器性能取决于事务大小和当前的服务器负载。运行查询的营业时间或如果不可能继续引用完整性,选择…。到输出文件,然后加载到另一个表;选择部分将会更快和非锁定。
- 的表tmp_ids_to_remove应该索引pt-archiver以来每一列需要索引快速检查被删除的行吗
- 如果你需要清洗的行各种GB /存档,你应该调整”,“条件一次只处理几百万行和过程批次中的行。试图执行一个巨大的事务(通过填充一个足够大的tmp_ids_to_remove或清洗/归档所有行)将性能不利。
注:以上解决方案的目标是数据一致性的代价性能。如果出于某种原因清洗/存档会中途停止,你还知道哪些行id用于清除,因为他们还在继续tmp_ids_to_remove表。
GitHub库,你可以找到一个示例场景文件和一个示例脚本做一个测试档案。脚本POC(的概念),您应该执行一个测试env:
使用说明:
- 下载的脚本:
|
1
2
|
旋度
https
:/ /生
.githubusercontent
com/ctutte/blog_complex_archive/主/设置
. sql
>
设置
. sql
旋度
https
:/ /github
com/ctutte/blog_complex_archive/团/主/archiver_script
. sh
>
archiver_script
. sh
|
- 创建测试环境:
|
1
|
mysql
- - - - - -u
根
- - - - - -p
<
设置
. sql
|
- 配置脚本:
|
1
|
修改文件权限
一个+x
archiver_script
. sh
|
- archiver_script。sh配置各种参数在顶部(用户名/密码/ SOURCE_DSN)
- 最后,执行该脚本:
|
1
|
。/archiver_script
. sh
|
从DB归档删除行,行写入存档/ tmp / table_name.out文件。
结论
试图清洗/档案行复杂的条件或当试图保持数据一致性可以是困难的。上面的解决方案将生成一个中间表和基于pt-archiver清除/归档行整洁的方式,可以自动能够清洗/归档数百万行,否则不可能做手工。
请注意:这个例子是来自一个真实的情况,但混淆和简化。它可能似乎仍“不必要的复杂”,但它一直这样,这样建议的解决方案是很有意义的。
在相似的场景,更容易/更快的解决方案可能是合适的,但是有时由于业务逻辑或其他限制,必须实现更复杂的解决方案。
这个问题





