原创作者:爱可生开源社区

背景

应用 JDBC 连接参数采用 useCursorFetch=true,查询结果集存放在 mysqld 临时表空间中,导致ibtmp1 文件大小暴增到90多G,耗尽服务器磁盘空间。为了限制临时表空间的大小,设置了:

innodb_temp_data_file_path = ibtmp1:12M:autoextend:max:2G

问题描述

在限制了临时表空间后,当应用仍按以前的方式访问时,ibtmp1文件达到2G后,程序一直等待直到超时断开连接。 SHOW PROCESSLIST显示程序的连接线程为sleep状态,state和info信息为空。 这个对应用开发来说不太友好,程序等待超时之后要分析原因也缺少提示信息。

问题分析过程

为了分析问题,我们进行了以下测试

测试环境:

  • mysql:5.7.16
  • java:1.8u162
  • jdbc 驱动:5.1.36
  • OS:Red Hat 6.4

1. 手工模拟临时表超过最大限制的场景

模拟以下环境:

  • ibtmp1:12M:autoextend:max:30M
  • 将一张 500万行的 sbtest 表的 k 字段索引删除

运行一条 group by 的查询,产生的临时表大小超过限制后,会直接报错:

select sum(k) from sbtest1 group by k; ERROR 1114 (HY000): The table '/tmp/#sql_60f1_0' is full 

2. 检查驱动对 MySQL 的设置

我们上一步看到,SQL手工执行会返回错误,但是 jdbc 不返回错误,导致连接一直 sleep,怀疑是 mysql 驱动做了特殊设置,驱动连接 mysql,通过 general_log 查看做了哪些设置。未发现做特殊设置。

3. 测试 JDBC 连接

问题的背景中有对JDBC做特殊配置:useCursorFetch=true,不知道是否与隐藏报错有关,接下来进行测试:

发现以下现象:

  • 加参数 useCursorFetch=true时,做同样的查询确实不会报错
  • 这个参数是为了防止返回结果集过大而采用分段读取的方式。即程序下发一个 sql 给 mysql 后,会等 mysql 可以读结果的反馈,由于 mysql 在执行sql时,返回结果达到 ibtmp 上限后报错,但没有关闭该线程,该线程处理 sleep 状态,程序得不到反馈,会一直等,没有报错。如果 kill 这个线程,程序则会报错。
  • 不加参数 useCursorFetch=true时,做同样的查询则会报错

结论

  1. 正常情况下,sql 执行过程中临时表大小达到 ibtmp 上限后会报错;
  2. 当JDBC设置 useCursorFetch=true,sql 执行过程中临时表大小达到 ibtmp 上限后不会报错。

解决方案

  • 进一步了解到使用 useCursorFetch=true 是为了防止查询结果集过大撑爆 jvm;
  • 但是使用 useCursorFetch=true 又会导致普通查询也生成临时表,造成临时表空间过大的问题;
  • 临时表空间过大的解决方案是限制 ibtmp1 的大小,然而 useCursorFetch=true 又导致JDBC不返回错误。
  • 所以需要使用其它方法来达到相同的效果,且 sql 报错后程序也要相应的报错。除了 useCursorFetch=true 这种段读取的方式外,还可以使用流读取的方式。流读取程序详见附件部分。
  • 报错对比
  • 段读取方式,sql 报错后,程序不报错
  • 流读取方式,sql 报错后,程序会报错
  • 内存占用对比

这里对比了普通读取、段读取、流读取三种方式,初始内存占用 28M 左右:

  • 普通读取后,内存占用 100M 多
  • 段读取后,内存占用 60M 左右
  • 流读取后,内存占用 60M 左右

补充知识点

MySQL共享临时表空间知识点

MySQL 5.7在 temporary tablespace上做了改进,已经实现将 temporary tablespace 从 ibdata(共享表空间文件)中分离。并且可以重启重置大小,避免出现像以前 ibdata 过大难以释放的问题。

其参数为:innodb_temp_data_file_path

1. 表现

MySQL启动时 datadir 下会创建一个 ibtmp1 文件,初始大小为 12M,默认值下会无限扩展:

通常来说,查询导致的临时表(如group by)如果超出 tmp_table_size、max_heap_table_size 大小限制则创建 innodb 磁盘临时表(MySQL5.7默认临时表引擎为 innodb),存放在共享临时表空间;

如果某个操作创建了一个大小为100 M的临时表,则临时表空间数据文件会扩展到 100M大小以满足临时表的需要。当删除临时表时,释放的空间可以重新用于新的临时表,但 ibtmp1 文件保持扩展大小。

2. 查询视图

可查询共享临时表空间的使用情况:

SELECT FILE_NAME, TABLESPACE_NAME, ENGINE, INITIAL_SIZE, TOTAL_EXTENTS*EXTENT_SIZE AS TotalSizeBytes, DATA_FREE,MAXIMUM_SIZE FROM INFORMATION_SCHEMA.FILES WHERE TABLESPACE_NAME = 'innodb_temporary'G*************************** 1. row *************************** FILE_NAME: /data/mysql5722/data/ibtmp1TABLESPACE_NAME: innodb_temporary ENGINE: InnoDB INITIAL_SIZE: 12582912 TotalSizeBytes: 31457280 DATA_FREE: 27262976 MAXIMUM_SIZE: 314572801 row in set (0.00 sec)

3. 回收方式

重启 MySQL 才能回收

4. 限制大小

为防止临时数据文件变得过大,可以配置该 innodb_temp_data_file_path (需重启生效)选项以指定最大文件大小,当数据文件达到最大大小时,查询将返回错误:

innodb_temp_data_file_path=ibtmp1:12M:autoextend:max:2G

5. 临时表空间与 tmpdir 对比

共享临时表空间用于存储非压缩InnoDB临时表(non-compressed InnoDB temporary tables)、关系对象(related objects)、回滚段(rollback segment)等数据;

tmpdir 用于存放指定临时文件(temporary files)和临时表(temporary tables),与共享临时表空间不同的是,tmpdir存储的是compressed InnoDB temporary tables。

可通过如下语句测试:

CREATE TEMPORARY TABLE compress_table (id int, name char(255)) ROW_FORMAT=COMPRESSED;CREATE TEMPORARY TABLE uncompress_table (id int, name char(255)) ;

附件

SimpleExample.java

import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Properties;import java.util.concurrent.CountDownLatch;import java.util.concurrent.atomic.AtomicLong;public class SimpleExample { public static void main(String[] args) throws Exception { Class.forName("com.mysql.jdbc.Driver"); Properties props = new Properties(); props.setProperty("user

sql 临时表_深度分析 | JDBC与MySQL临时表空间的分析相关推荐

  1. mysql印度时区_一次 JDBC 与 MySQL 因 “CST” 时区协商误解导致时间差了 14 或 13 小时的排错经历...

    CST 时区 名为 CST 的时区是一个很混乱的时区,有四种含义: 美国中部时间 Central Standard Time (USA) UTC-06:00 澳大利亚中部时间 Central Stan ...

  2. mysql 临时表_第05问:MySQL 在处理临时结果集时,内部临时表会使用多少内存?...

    问题: MySQL 在处理临时结果集(UNION 运算 / 聚合运算等)时,会用到内部临时表(internal temporary table). 那么内部临时表会使用多少内存呢? 实验: 我们先创建 ...

  3. jdbc连接云数据库mysql数据库_如何通过JDBC连接MySQL数据库

    通过JDBC连接MySQL数据库,代码中的JDBC链接格式如下: jdbc:mysql://:/?sslmode=verify-full&sslrootcert= 表1参数说明参数 说明 如果 ...

  4. 腾讯云mysql全日制分析_腾讯云:MySQL数据库的高可用性分析

    MySQL数据库是目前开源应用最大的关系型数据库,有海量的应用将数据存储在MySQL数据库中.存储数据的安全性和可靠性是生产数据库的关注重点.本文分析了目前采用较多的保障MySQL可用性方案. MyS ...

  5. python拼接sql语句_【Python】拼接MySQL常用语句

    import pymysql class MK_sql (): """ 构建mySQL常见语句:增删改查排序 """ def __init_ ...

  6. 阿里云 mysql 表锁死_解决阿里云数据库MySQL实例空间满自动锁问题

    MySQL实例可能会由于SQL语句.外部攻击等原因导致实例空间满,为避免数据丢失,RDS会对实例进行自动锁定,磁盘锁定之后,将无法进行写入操作. 背景信息 当实例由于实例空间满自动锁定时,控制台可以在 ...

  7. mysql死锁释放时间参数_由FTWRL导致的MySQL从库死锁分析及参数深究

    最近线上执行备份的从库时出现复制卡死现象,分析以后发现是两个死锁,show full processlist的状态如图1所示,其中,数据库版本是官方5.7.18版本,我们内部做了些许修改,但与此次死锁 ...

  8. mysql中递增列_如何使用JDBC在MySQL中创建带有自动递增列的表?

    在创建表时,在某些情况下,我们需要自动生成/增加列的值(例如ID).各种数据库以不同的方式支持此功能. 在MySQL数据库中,您可以使用以下语法声明列自动递增.CREATE TABLE table_n ...

  9. hive sql练习_经典的SparkSQL/Hive-SQL/MySQL面试-练习题

    经典的SparkSQL/Hive-SQL/MySQL面试-练习题​mp.weixin.qq.com 第一题 需求: 已知一个表order,有如下字段:date_time,order_id,user_i ...

最新文章

  1. Leetcode | Binary Tree Maximum Path Sum
  2. 宏基因组蚂蚁森林公益合种树项目,支持祖国绿化事业,让世界更美好
  3. java 反序列化利用工具 marshalsec 使用简介
  4. 全国计算机等级考试题库二级C操作题100套(第97套)
  5. .NET Core Run On Docker By Kubernetes 系列文章汇总
  6. hide show vue 动画_Vue2.x学习四:过渡动画
  7. AndroidJava List与equals的微妙关系,小心掉坑里
  8. 几张一模一样的照片_两张一模一样的照片看起来却不一样!什么鬼?
  9. Java笔记-JdbcTemplate批量执行insert及update
  10. css技巧中placeholder的颜色
  11. Linux虚拟机安装谷歌浏览器和驱动
  12. python正态分布函数_Python正态分布概率计算方法
  13. 为什么说优秀的管理都是自下而上的?
  14. 天津理工大学计算机项目管理实验四,天津理工大学软件工程实验报告4.docx
  15. 谷歌开源!一个格式化 Python 代码的好帮手!
  16. unrar - 解压rar文件
  17. cs224w(图机器学习)2021冬季课程学习笔记4 Link Analysis: PageRank (Graph as Matrix)
  18. html动画翻书特效,css3 做一个类似于翻书特效的3D动画
  19. java 8函数式编程pdf 百度云盘链接
  20. 【unity2d】教会你如何做一个自动升降平台

热门文章

  1. ssis导出数据性能_如何使用SSIS将数据从Excel导出到Azure SQL数据库中的多个表
  2. 使用CompletableFuture实现业务服务的异步调用实战代码
  3. C语言拾遗(二):符号重载
  4. GDALSetProjection使用的一个注意事项
  5. Python中print()函数不换行的方法
  6. 超文本标记语言HTML
  7. Bootstrap 弹出框(Popover)插件
  8. PHP面向对象构造函数,析构函数
  9. [USACO] Gold组刷题记录
  10. 常见MIME类型例表