暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

第38问:分区表到底要上多少锁

287

为什么我使用分区表, 有时候是几个锁, 有时候是几百把锁, 阴晴不定

实验

我们先宽油起一个数据库:

建一个分区表:

我们希望根据 timestamp 的日期进行分区, id 作为主键. 由于分区键必须是主键, 所以我们将 timestamp 加入主键中.

下面我们来研究一下使用分区表时, 分区表到底会用多少个锁.

先插入两条数据:

场景1:

我们用 RC 隔离级别, 锁定 id = 1 的记录

此时, 查看锁信息:

可以看到:

由于我们在 where 条件里没有用到分区键 timestamp , 那么 MySQL 要访问每张表, 就需要给每张表上 IX 锁.

场景2:

这次我们换成 RR 隔离级别:

查看锁信息:

这次锁数量变成了 64 个, 每个分区表上锁住了 supremum 的 gap 区间. 这很好理解: 我们让 MySQL 锁住了所有 id=1 可能出现的地方, 这就包括了所有分区中相关间隙.

场景3:

这次我们在 where 条件里用到分区键:

查看锁信息:
由于我们直接使用了分区键, 这次只有相关的分区会有锁.
看上去 where 条件中使用分区键, 能大量减少锁的范围.

场景4:

我们在 where 中只使用分区键, 但是条件复杂一点, 换成比较符(大于/小于):
查看锁信息:

可以看到各分区上的 IX 锁又出现了, 跟场景3的结论又出现了偏差.

我们先不着急, 再做一个实验

场景5:

这次我们做一张类似的表, 只是将分区键函数换成了 YEAR
使用场景4类似的 SQL:
查看锁信息:

这里的锁只涉及 p0 和 p1 (也就是包含匹配where条件的数据的分片), 不包括不相关的分片 p2这次测试又和场景3的结论一致了

场景3/4/5的结论不一致, 我们怎么理解呢? 还得回到官网:MySQL 可以根据 where 条件中的分片键信息, 过滤出相关的分片, 仅在相关分片上用锁, 这技术成为 partition pruning.但这项优化有限制条件, 这里我们节选一段官网文档, 详细信息大家参考:https://dev.mysql.com/doc/refman/8.0/en/partitioning-pruning.html

在场景4和场景5中, 在 where 中使用了比较符的情况下, 场景4中的 DAYOFYEAR 函数是不支持 partition pruning 的, 而场景5中的 YEAR 函数则能支持, 所以两个场景存在差异.

通过今天的实验, 我们可以看到:对分区表的使用中, where 中带有分区键, 并且形式简单 ("等于" 比 "比较符" 简单), 并且分区键中的函数符合条件 ( YEAR/TO_DAYS/TO_SECONDS/...),  那么 partition pruning 机制会优化上锁的数量.否则, 分区表的使用会带来锁数量的上升.

小贴士

也可以通过 select ... from table partition(p1) where ... , 将SQL的作用范围限定在某个分片的范围内。

但这样对业务的侵入就比较严重, 可作为非常手段使用

思考题

大家有空可以思考以下现象的原因:

我们造一张与之前实验类似的表, 造一些数据:

与场景1下同样的SQL:
查看锁信息:

发现与场景1不同, 除了所有分区上都有IX锁, 所有行都上有行锁

大家有兴趣的时候, 可以尝试解释这个现象

相关推荐
第37问:自旋锁 旋着旋着人就糊涂了
第36问:用 mysqlslap 压测的结果,为什么比用 sysbench 的结果平稳?
第35问:InnoDB 刷脏页慢,会影响我的业务么?

关于 MySQL 的技术内容,你们还有什么想知道的吗?赶紧留言告诉小编吧!

本文关键字:#分区# ##
想看更多技术好文,点个“在看”吧!
文章转载自爱可生开源社区,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论