前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL案例 | consider increasing server sort buffer

MySQL案例 | consider increasing server sort buffer

作者头像
老叶茶馆
发布2021-03-30 15:37:58
9670
发布2021-03-30 15:37:58
举报

作者:八怪(高鹏) 中亦科技数据库专家

今天一个错误反馈到我这边,我还是第一次遇到这种错误,然后就分析了一下,因为以前曾经做过filesort流程分析,新书《深入理解MySQL主从原理》中也有一节专门介绍这部分。这里简单做了一下debug后分析出原因。

问题版本5.7.27,我的测试版本5.7.22。

一、问题模拟

代码语言:javascript
复制
mysql> show create table testsorterr3 \G
*************************** 1. row ***************************
       Table: testsorterr3
Create Table: CREATE TABLE `testsorterr3` (
  `id` int(11) DEFAULT NULL,
  `name1` varchar(510) NOT NULL,
  `name2` varchar(510) NOT NULL,
  UNIQUE KEY `name1` (`name1`,`name2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> select count(*) from testsorterr3 ;
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

mysql> show variables like 'sort_buffer_size';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| sort_buffer_size | 32768 |
+------------------+-------+
1 row in set (0.02 sec)


mysql>  select id from testsorterr3 order by id;
ERROR 1038 (HY001): Out of sort memory, consider increasing server sort buffer size

当然问题解决很简单,加大sort_buffer_size 设置即可。

但是这里实际上为32K,我只是按照一个int类型的4字节类型进行排序而已,并且表中一条数据都没有报错显然有点让人摸不到头脑说sort_buffer_size设置小了。

再说sort_buffer_size不够不是可以使用临时文件做归并排序嘛?

二、问题分析

注意这里只谈 original filesort algorithm(回表排序)。

先来看看抛错点

代码语言:javascript
复制
    if (memory_available < min_sort_memory)
    {
      my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERRORLOG + ME_FATALERROR));
      goto err;
    }

这里memory_available 就是我们sort_buffer_size 的设置大小,这里就是32K。min_sort_memory则是通过计算得到的如下:

代码语言:javascript
复制
    const ulong min_sort_memory=
      max<ulong>(MIN_SORT_MEMORY,
                 ALIGN_SIZE(MERGEBUFF2 * (param.rec_length + sizeof(uchar*))));

其中MIN_SORT_MEMORY为32K,MERGEBUFF2 为15。

那么剩下的变量实际上就只有param.rec_length一个了,这实际上是计算出来的排序字段的长度。

而对于original filesort algorithm(回表排序)而言这个值实际上包含的是:

主键(或者非空唯一建或者rowid) + 排序字段长度

我们来简单debug一下:

代码语言:javascript
复制
(gdb) p ref_length
$28 = 3064
(gdb) p sort_length
$29 = 5
(gdb) 

可以看到这里3064字节,大概就是510*2*3的长度,因为我们这里非空唯一键为(`name1`,`name2`),Innodb表正是按照它进行组织的,而sort_length为5是int类型(4字节)再加上可以为null(1字节)也就是5字节。

好了,我们大概计算一下,那么

MERGEBUFF2 * (param.rec_length + sizeof(uchar*)))

忽略一个指针的大小,大概就是

15 *( 3064+5),约为45k左右

比sort_buffer_size设置的32K还要大,所以报错了。

并且整个计算过程还没有真正的进行排序,因此即便是空表也会进行计算,和数据量无关。就是本案中MySQL认为sort_buffer_size连一行排序数据都装不下产生报错的原因。

三、如何避免

显然这个问题和表的设计有关,如果遵循开发设计规范,采用自增INT做主键,问题自然解决,这是治本

当然简单地加大sort_buffer_size,这是治标

全文完。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老叶茶馆 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、问题模拟
  • 二、问题分析
  • 三、如何避免
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档