您的位置:首页 > 数据库 > MySQL

一条Select语句引发的反思

2017-11-13 19:38 267 查看
最近在写一个数据转储的程序,功能是从源数据库读取数据、对数据加工、插入到指定数据库。采用的方式是调用
mysql -e
将查询的结果重定向到指定文件。

eg: mysql -hxxx -uxxx -pxxx DatabaseName -e "select * from t_test;" > test


测试过程中:

源数据库的数据量少:

程序正常运行,没有任何异常

源数据库的数据量大(21G,2亿+条)

因为在程序中直接调用
mysql
来执行,在使用
top
命令对程序使用的内存进行监控的时候,发现15S,mysql的内存占用量已经达到50%(4核,8G机器)

分析原因:

测试mysqldump命令的内存和CPU占用量

cpu的占用率为50%左右,内存始终维持在0.1

为什么不用mysqldump命令?

因为不合适,这里的使用场景之一是将源数据库的指定列都读取出来,加工,插入到目标数据库。mysqldump主要的使用场景是对数据库的复制。

mysql命令行直连mysql server测试

内存升的更快,内存在5S的时候就升到了40%

终极大招——Google+Stackoverflow

烟雾弹

由于笔者读东西一直是一目十行的,所以在查到https://bugs.mysql.com/bug.php?id=77403这个mysql的bug后就查了下产品预发布和线上的MySQL的版本,哈哈,居然都是5.6(小版本忽略),于是很高兴的跟老板说,这个问题是MySQL的bug。

老板用来2秒钟大致看了下文档,告诉我这个跟我的问题不一样,解释下这个mysql的bug是有人发现5.5的MySQL升级到5.6.25后发现MySQL Server 的内存使用量暴增,而我的是客户端的内存 使用量暴增。感觉差点想要找一个地缝钻进去,唉,做人还是要认真!!!

正解

mysql [options] database

options中有个–quick的选项,详细解释如下:

-q, --quick         Don't cache result, print it row by row. This may slow

down the server if the output is suspended. Doesn't use

history file.


你以为这就结束了是不是,不,知其然还要知其所以然!

myql –quick命令介绍

以下这部分英语是直接摘自MySQL的英文帮助文档,笔者翻译水平有限,怕翻译有误,所以直接摘录过来。

Out of memory

If you issue a query using the mysql client program and receive an error like the following one, it means that mysql does not have enough memory to store the entire query result:

mysql: Out of memory at line 42, 'malloc.c'
mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)
ERROR 2008: MySQL client ran out of memory


To remedy the problem, first check whether your query is correct. Is it reasonable that it should return so many rows? If not, correct the query and try again. Otherwise, you can invoke mysql with the
--quick
option. This causes it to use the
mysql_use_result()
C API function to retrieve the result set, which places less of a load on the client (but more on the server).

归根节点就是在使用–quick的选项后,会强制调用
mysql_use_result()
的函数,我的理解是客户端不会缓存MySQL返回的结果而是直接打印出来,这样就不会撑爆内存。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql select mysqldump