博客
关于我
MySQL的KEY分区存在BUG,请慎用
阅读量:171 次
发布时间:2019-02-28

本文共 1567 字,大约阅读时间需要 5 分钟。

问题现象

上个星期在排查一个外包项目时,发现了一个非常奇怪的现象。该项目使用MySQL 5.7数据库管理几个频繁操作的表,并对这些表进行了key分区划分,分区数为10和100。创建表的语句类似于以下所示:

CREATE TABLE `tbl_key_partition` (    `id` varchar(64) NOT NULL COMMENT 'id',    `updateTime` datetime DEFAULT NULL    PRIMARY KEY (`id`)  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4  PARTITION BY KEY ()  PARTITIONS 100 ;

在观察过程中,发现所有的数据都分布在了偶数编号的分区上,而奇数编号的分区几乎没有数据。通过查询information_schema.partitions表或直接执行select count(*) from tbl_key_partition partition(p91),可以看到奇数编号分区的ibd文件大小始终固定为96K,而实际数据并未插入其中。这表明奇数编号分区完全没有数据。

问题重现

为了验证问题,用户在MySQL中手动创建了tbl_key_partition表,并使用load_data存储过程插入了10万条数据。存储过程的源码如下:

delimiter $$  CREATE PROCEDURE load_data (in num int)  BEGIN    DECLARE v INT DEFAULT 0;    WHILE v < num DO      INSERT INTO tbl_key_partition VALUES (concat(substring(md5(rand()), 1, 10), v), date_add('2020-01-01 00:00:00', interval v second));      SET v = v + 1;    END WHILE;  END$$  delimiter ;  call load_data(100000);

在插入数据后,用户发现数据基本上都写到了偶数编号的分区上,而奇数编号的分区只写了极少数的数据。同时,奇数编号分区的ibd文件大小始终保持在96K,这进一步证明了奇数编号分区没有实际数据。

原因分析

MySQL key 分区原理

key分区的原理是通过MySQL内置的哈希算法对分片键计算哈希值后,再对分区数取模来实现数据的分布分区。与哈希分区类似,key分区的哈希函数由MySQL服务器提供。在NDB集群中,通常使用MD5()函数来实现哈希计算。而对于其他存储引擎的表,MySQL服务器使用基于PASSWORD()函数的内部散列函数来生成哈希值。

原因

通过对问题的深入分析,发现这是一个MySQL 5.7的已知bug,尽管官方没有明确说明,但许多技术文章和论坛讨论了这一问题。具体来说,当分区数为偶数时,key分区的哈希函数可能存在偏移,导致数据无法均匀分布到所有分区中。例如,当分区数为10或100时,数据主要分布在偶数编号的分区,而奇数编号的分区几乎没有数据。

此外,许多文章指出,只有当分区数为质数时,key分区才能保证数据的均匀分布。例如,分区数为11、13或17时,数据分布较为均匀。而如果分区数为偶数(如64或128),则会导致奇数编号的分区完全没有数据。对于奇数但非质数的分区数(如63或121),数据分布虽然不均匀,但仍然会有数据存在于所有分区中。

综上所述,使用key分区在分区数为偶数时存在问题,建议避免使用key分区,而改用hash分区或范围分区来实现数据的分布分区。

转载地址:http://iubc.baihongyu.com/

你可能感兴趣的文章
mysql启动报错
查看>>
mysql启动报错The server quit without updating PID file几种解决办法
查看>>
mysql命令
查看>>
mysql命令==_mysql命令
查看>>
mysql命令和mysql的配置文件
查看>>
watch
查看>>