为什么我们要从MySQL迁移到TiDB?
当一张百亿数据量的表放在你面前,你将面临着什么?加列?哭吧,怎么也得等个几天甚至几周。加索引?哭吧,不论你用 pt-online-schema,还是 gh-ost,你都面临着拷贝一张临时表用以存储临时数据,磁盘已经 80% 了,这一张表就占几百 G,你咋弄?
图片来自 Pexels
我先说几个最让你兴奋和开心的点吧:
在 TiDB 里,你完全不用担心磁盘容量的问题。
在 TiDB 里,原生支持 Online DDL,你完全不用担心第三方改表工具改表出现各种 Bug 的问题,相信用开源工具改过上 T 级别表的同学都遇到过或多或少的各类 error。
在 TiDB 里,加列,主键扩容字段都是秒级的,比如我刚刚就刚对一张 19 亿的表加完了字段,1 秒完事,这在 MySQL 里要 8.0 才可以,而且还要求列在最后才行。
在 TiDB 里,你会发现 count(*) 惊人的快,一张近 20 亿的表 coun(*) 大概在 1 分钟完事儿,当然,这取决于你的 KV 数量和磁盘性能。
在 TiDB 里,从 MySQL 迁移将变得简单,图形化一键迁移,爽不爽?
在 TiDB 里,绝大多数情况你会发现比单机 MySQL 有更好的性能,当然也不排除一些例外,例如 enum 这样奇葩的字段类型。
在 TiDB 里,......,您且往下看,我慢慢和您说。
使用背景
集群架构
说起 DM 使用这块文章后面会单独分享下这块需要注意的问题,如下图所示:
TiDB 在 360 云平台的使用情况
一键迁移工具 DM 干货分享
DM 使用经验如下:
①权限
SELECT
UPDATE
ALTER
CREATE
DROP
INSERT
DELETE
上游 (REPLICATION SLAVE 权限必须具备,要不增量同步会 access deny)。
下游 (不加 super 会导致 checksum table 无法执行)。
②TiKV Region Score
balance-leader 关注 Region 的 Leader,目的是分散处理客户端请求的压力。
balance-region 关注 Region 的各个 Peer,目的是分散存储的压力,同时避免出现爆盘等状况。
我们这里重点关注的是 balance-region,当它出现不均衡的时候,我们可以直接在监控中看到类似下图所示:
如何控制或减小 Region Balance 大规模迁移时对业务的影响;
如何提前规避因磁盘导致的大规模 Region Balance。
high-space-ratio 0.7 #设置空间充裕阈值为 0.7。当节点的空间占用比例小于指定值时,PD 调度时会忽略剩余空间这个指标,主要针对实际数据量进行均衡。
region-schedule-limit 8 #最多同时进行 8 个 Region 调度。这个值主要影响 Region Balance 的速度,值越大调度得越快,设置为 0 则关闭调度。Region 调度的开销较大,所以这个值不宜调得太大。也可以通过减小该值来限制调度region对集群产生的影响。
merge-schedule-limit 12 #最多同时进行 12 个 merge 调度。设置为 0 则关闭 Region Merge。Merge 调度的开销较大,所以这个值不宜调得过大。
leader-schedule-limit 8 #最多同时进行 8 个 leader 调度。这个值主要影响 Leader Balance 的速度,值越大调度得越快,设置为 0 则关闭调度。Leader 调度的开销较小,需要的时候可以适当调大。
max-merge-region-keys 50000 #设置 Region Merge 的 keyCount 上限为 50k。当 Region KeyCount 大于指定值时 PD 不会将其与相邻的 Region 合并。
max-merge-region-size 16 #设置 Region Merge 的 size 上限为 16M。当 Region Size 大于指定值时 PD 不会将其与相邻的 Region 合并。设置为 0 表示不开启 Region Merge 功能。
例如当我们在 Drop 大量的表后,会产生很多的空 Region。在 Region 数量较多的情况下,Raftstore 需要花费一些时间去处理大量 Region 的心跳,从而带来一些延迟,导致某些读写请求得不到及时处理。
如果读写压力较大,Raftstore 线程的 CPU 使用率容易达到瓶颈,导致延迟进一步增加,进而影响性能表现。
因此我们会希望尽快的进行 Region Merge,来避免过多的 Region 对集群造成性能损耗时,我们可以同时调小 max-merge-region-keys、max-merge-region-size,来让其更快的触发 Merge 操作,同时调大 merge-schedule-limit 提高并发度。
例如当我们发现某台 KV 磁盘空间剩余 40% 开始大量调度时,我们可以将 high-space-ratio 调整到 0.7,以临时避免调度对业务产生的影响。
我们也可以控制调度的并发度,来减少对业务产生的影响,实测这都是立竿见影的参数,大家如果遇到这些问题可供参考。
这时 PD 的 store region score 就会相比其他节点出现异常,引起性能抖动和 Duration 升高。
Duration 恢复正常水平,如下图 16:54 分时的情况:
QPS 也不再积压,恢复正常水准:
例如将 Expires 配置为 7,代表 7 天后删除:
[purge]
interval = 3600
expires = 7
remain-space = 15
④关于 DM 使用期间出现数据丢失的问题
在早期还没有 dm-portal 自动化生成 task 时,我们都是自行编写 DM 的 task 同步文件。后来有了 dm-portal 自动化生成工具,只要图形页面点点点就可以了。
我们也已经反馈给了官方。未来不久的版本估计就可以修复。
["skip event"] [task=task_20357] [unit="binlog replication"] [event=query] [statement="ALTER TABLE `360`.`_data_201910_gho` ADD COLUMN `raw_url_md5` CHAR(32) NOT NULL DEFAULT '' COMMENT 'raw_url md5'"]
["skip event"] [task=task_20357] [unit="binlog replication"] [event=query] [statement="ALTER TABLE `360`.`_data_201910_gho` ADD INDEX `idx_rawurl_md5`(`raw_url_md5`)"] [schema=flow]
["skip event"] [task=task_20357] [unit="binlog replication"] [event=query] [statement="ALTER TABLE `360`.`_data_201910_gho` DROP INDEX `idx_raw_url`"] [schema=flow]
⑤关于 DM 使用期间偶发性 1062 主键冲突的问题
query-error task 能看到具体的报错信息,下游看都没有该值:
mysql> select * from client where clientid='82b51e6f6eb64955487f978dd94a2c81e492f6170xxxxxxxxxxxxxxxxxxxxxxxxx';
Empty set (0.00 sec)
再去上游看,结果发现也没有值,业务逻辑应该是后来 delete 了:
mysql> select * from client where clientid='82b51e6f6eb64955487f978dd94a2c81e492f6170xxxxxxxxxxxxxxxxxxxxxxxxx';
Empty set (0.00 sec)
alter table dsp_group_media_report drop partition p202006 ,p202007 ;
Alter table dsp_group drop column test_column;
定位到是:
mysql> show global variables like 'tidb_ddl_reorg_worker_cnt';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| tidb_ddl_reorg_worker_cnt | 16 |
+---------------------------+-------+
1 row in set (0.11 sec)
mysql> show global variables like 'tidb_ddl_reorg_batch_size';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| tidb_ddl_reorg_batch_size | 1024 |
+---------------------------+-------+
上述两个参数对已有非 pcie 集群压力比较大导致。通过 set global 调节(3.0.3 后,默认从 256 涨到了 1000 和 16):
tidb_ddl_reorg_batch_size 1000-256
tidb_ddl_reorg_worker_cnt 16-4
同时,提高 Compaction 相关:
max-background-jobs: 8-10-12
max-sub-compactions: 1-2-4
defaultcf.compression-per-level: ["lz4", "lz4", "lz4", "lz4", "lz4", "zstd", "zstd"]
writecf.compression-per-level: ["lz4", "lz4", "lz4", "lz4", "lz4", "zstd", "zstd"]
最终的优化结果是,QPS 稳定在 3K 左右:
参数如下:
raftstore.hibernate-regions: true
在 DM 导入集群期间,确实会因为写热点的问题导致集群整体 Duration 更高,因为 IO 争用会更明显。这里其实也是可以通过一些参数来让集群运行的更快的。
如下参数从原值调到-新值:
raftstore:
apply-pool-size: 3-4
store-pool-size: 3-4
storage:
scheduler-worker-pool-size: 4-6
server:
grpc-concurrency: 4-6
rocksdb:
max-background-jobs: 8-10
max-sub-compactions: 1-2
可以看到效果如下:QPS 不再抖动,Duration 也恢复到正常的水平。
我们的场景是 TiKV 上没有明显的瓶颈,主要慢在了 scheduler latch wait duration,可以调下参数看看:
storage:
scheduler-concurrency: 204800000
raftstore:
raft-max-inflight-msgs: 4096
其他干货打包分享
官方建议更换规则:
sum(increase(tikv_gcworker_gc_tasks_vec{task="gc"}[1d]))
在 TiDB 中,如下查询是不能用到索引的:
select * from manual_domain where host_md5 = '55fbea39965484a61xxxxxxxxxx' or domain_md5 = '55fbea39965484a61xxxxxxxxxx';
业务反馈查询变慢,发现是另外一个业务全表扫 insert into select 导数据导致的。
[2019/09/18 10:04:37.339 +08:00] [INFO] [tracker.rs:150] [slow-query] [internal_key_skipped_count=46649] [internal_delete_skipped_count=0] [block_cache_hit_count=1596] [block_read_count=9] [block_read_byte=31933] [scan_first_range="Some(start: 7480000000000002285F72800000000021E9BD end: 7480000000000002285F72800000000024199A)"] [scan_ranges=1] [scan_iter_processed=46650] [scan_iter_ops=46652] [scan_is_desc=false] [tag=select] [table_id=552] [txn_start_ts=411244239493267464] [wait_time=2ms] [total_process_time=1.41s] [peer_id=ipv4:192.168.1.248:45686] [region_id=835437]
enum 在 TiDB 3.0.2 进行 where 条件查找是,发现不能下推到 TiKV。官方说4.0GA 修复。临时办法是修改到其他类型。
enum modify 为 tinyint 发现内容出现变化,原本的’'变成了 default 值,‘1’ 变成了 2,经测试 varchar 正常,因此不要尝试去变更 DM 备份出来的 Schema 文件来实现表结构变更,应该从上游 MySQL 解决。
tidb_batch_insert
tidb_batch_delete
tidb_dml_batch_size
在使用 Mydumper 备份大时,会打满 TiDB 网卡,同时会消耗 TiDB、TiKV 更多的内存。
【TiDB ERR】[emergency]TiDB_schema_error:192.168.1.1:10080,[add_dba_mysql]【360】
【TiDB ERR】[critical]NODE_memory_used_more_than_80%:192.168.1.2:9100,[add_dba_mysql]【360】
去抓取慢日志会看到如下内容:
grep Query_time tidb_slow_query-2019-12-24T04-53-14.111.log|awk -F : '$2>10'
# Time: 2019-12-24T03:18:49.685904971+08:00
# Txn_start_ts: 413433784152621060
# User: backup@192.168.1.3
# Conn_ID: 4803611
# Query_time: 4002.295099802
SELECT /*!40001 SQL_NO_CACHE */ * FROM `360`.`t_d` ;
展望
简介:360 数据库运维资深工程师,《MongoDB 运维实战作者》,知名论坛 MySQL 版主,51CTO 博客之星,闲暇之余,喜欢将部分案例写成博客,累计访问量过百万。
链接:https://blog.51cto.com/suifu/2476758
编辑:陶家龙
征稿:有投稿、寻求报道意向技术人请联络 editor@51cto.com
精彩文章推荐: