为什么MySQL会说我内存不足?


9

我试图INSERT...SELECT用JDBC在MySQL中执行相当大的操作,但出现以下异常:

Exception in thread "main" java.sql.SQLException: Out of memory (Needed 1073741824 bytes)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)

由于我实际上没有返回ResultSet对象,因此我认为Java堆空间应该不是问题。但是,无论如何,我都尝试将其调高,但效果不好。然后,我尝试在MySQL Workbench中执行该语句,并且得到了基本上相同的东西:

Error Code 5: Out of memory (Needed 1073741816 bytes)

我应该有足够的RAM来完成这些操作(足以容纳要从中选择的整个表),但是我猜测我需要调整各种设置以利用我的所有内存。我正在使用Windows Server 2008 AMI 运行Amazon EC2 高内存双超大实例。我尝试摆弄my.ini文件以使用更好的设置,但就我所知,我可能会使情况变得更糟。这是该文件的转储:

[client]
port=3306
[mysql]
default-character-set=latin1
[mysqld]
port=3306
basedir="C:/Program Files/MySQL/MySQL Server 5.5/"
datadir="C:/ProgramData/MySQL/MySQL Server 5.5/Data/"
character-set-server=latin1
default-storage-engine=INNODB
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
max_connections=100
query_cache_size=1024M
table_cache=256
tmp_table_size=25G
thread_cache_size=8
myisam_max_sort_file_size=100G
myisam_repair_threads = 2
myisam_sort_buffer_size=10G
key_buffer_size=5000M
bulk_insert_buffer_size = 4000M
read_buffer_size=8000M
read_rnd_buffer_size=8000M
sort_buffer_size=1G
innodb_additional_mem_pool_size=26M
innodb_flush_log_at_trx_commit=2
innodb_log_buffer_size=13M
innodb_buffer_pool_size=23G
innodb_log_file_size=622M
innodb_thread_concurrency=18
innodb_file_per_table=TRUE
join_buffer_size=4G
max_heap_table_size = 10G

因此,是否只是更改上述设置以使其更适合我的环境而已?如果是这样,我应该使用哪些设置?我是唯一使用此实例的人。我将其用于个人兴趣项目,该项目涉及对大型数据集的统计分析。因此,我可以随意使用它来查询自己的所有可用资源。

如果这不是更改这些设置的问题,那是什么问题?感谢您提供的有关如何更好地配置所有内容的帮助。


任何使用1g查询缓存的人都不知道他们在做什么。

@winmutt您可能是正确的,但是您的评论如果没有进一步的解释,将对任何人都没有帮助。您能否提供您提出意见的理由来帮助我们?
Michael McGowan 2012年

一个方便的入门工具是tools.percona.com/wizard
KCD

Answers:


9

鉴于这是Windows安装,@ DTest仍然提供了正确的初始方向。

应用以下公式:

大多数人使用此:

Maximum MySQL Memory Usage = innodb_buffer_pool_size + key_buffer_size + (read_buffer_size + sort_buffer_size) X max_connections

我更喜欢这样:

Maximum MySQL Memory Usage = innodb_buffer_pool_size + key_buffer_size + ((read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size) X max_connections)

这些变量是您需要调整的变量,直到公式产生80%或更少的已安装RAM。

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections

4

我会尝试降低您的缓冲区大小。将它们放大到可能会导致问题。您有多少内存可用于运行这些值:

query_cache_size=1024M
myisam_max_sort_file_size=100G
myisam_sort_buffer_size=10G
key_buffer_size=5000M
bulk_insert_buffer_size = 4000M
read_buffer_size=8000M
read_rnd_buffer_size=8000M
sort_buffer_size=1G
innodb_buffer_pool_size=23G

一些缓冲区大小是按线程分配的,例如myisam_sort_buffer_size为10G会为每个线程分配10G。

我将首先大幅降低这些值,然后研究分配多少内存(如果有)真正需要哪些值。


4

确定MySQL认为可以分配多少内存的快速方法如下:

wget mysqltuner.pl

perl mysqltuner.pl

当您运行此脚本时,它将告诉您MySQL认为可以安全分配的已安装RAM的百分比。如果给出的答案超过100%,则肯定需要减小缓冲区大小。要重点关注的是:

sort_buffer_size的值
read_buffer_size
read_rnd_buffer_size
join_buffer_size
MAX_CONNECTIONS
key_buffer_size的(不是真的有效过去4G)

@DTest已经在他的答案中为您设置了方向,因此他的答案是+1。Perl脚本将告诉您如果未设置或更改任何值会发生什么。这是一个例子:

我的一个客户端的
read_buffer_size = 128K
read_rnd_buffer_size = 256K sort_buffer_size
= 2M
join_buffer_size = 128K
max_connections = 1050

这是mysqltuner.pl的输出:

MySQLTuner 1.2.0-重大Hayden
错误报告,功能请求和下载,位于http://mysqltuner.com/
使用'--help'运行以获取其他选项和输出过滤
请输入您的MySQL管理登录名:lwdba
请输入您的MySQL管理信息密码:

--------一般统计---------------------------------------- ----------
[-]跳过MySQLTuner脚本的版本检查
[确定]当前正在运行的受支持的MySQL版本5.0.51a-community-log
[!!]切换到64位操作系统-MySQL当前无法使用你所有的RAM

--------存储引擎统计信息--------------------------------------- ----
[-]状态:+ Archive -BDB +联合+ InnoDB -ISAM -NDBCluster
[-] MyISAM表中的数据:319M(表:108)
[-] InnoDB表中的数据:2M(表: 5)
[!!]碎片表总数:22

- - - - 性能指标 - - - - - - - - - - - - - - - - - - - - ---------
[-]上镜时间:52d 23h 15m 57s(72M q [15.875 qps],241K conn,TX:2B,RX:1B)
[-]读/写:59%/ 41%
[-]缓冲区总数:全局34.0M +每个线程2.7M(最多1050个线程)
[!!]在32位系统上分配> 2GB RAM可能导致系统不稳定
[!!]可能的最大内存使用量:2.8G (已安装RAM的72%)
[确定]慢查询:0%(54 / 72M)
[确定]可用连接的最高使用率:6%(65/1050)
[确定]关键缓冲区大小/ MyISAM索引总数:8.0M / 82.1M
[确定]关键缓冲区命中率:100.0%(4B缓存/ 1M读取)
[!!]禁用查询缓存
[OK]需要临时表的排序:0%(0个临时排序/ 948K排序)
[确定]在磁盘上创建的临时表:3%(磁盘上11K /总共380K)
[!!]线程缓存被禁用
[!!]表缓存命中率:0%(64个打开/ 32K打开)
[确定]打开文件使用的限制:2%(125 / 5K)
[确定]立即获得表锁:99%(立即3M锁/ 30M锁)
[确定] InnoDB数据大小/缓冲池:2.7M / 8.0M

--------建议----------------------------------------- ------------
一般建议:
运行OPTIMIZE TABLE来整理表有更好的表现
启用慢查询日志来解决不良查询
设置thread_cache_size的4个作为初始值
增加table_cache的逐渐以避免文件描述符限制
变量调整:
query_cache_size(> = 8M)
thread_cache_size(从4开始)
table_cache(> 64)

请注意效果指标

[-]缓冲区总数:全局3400万,每个线程2.7M(最多1050个线程)

MySQL可以根据/etc/my.cnf中的设置分配最多72%的已安装RAM。

34M基于结合的innodb_buffer_pool_size和key_buffer_size

每个线程2.7M基于read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size。

2.7M的倍数基于max_connections。

因此,您必须对这些参数进行调整,直到“性能指标”报告指出您已安装的RAM不足100%(最好是80%以下)。


我不确定是否可以使用您的工具;我正在使用Windows。该文档提到不支持Windows,但是我还是尝试了。当我尝试运行它时,它表明它在我的$ PATH中找不到mysqladmin,但是MySQL的bin目录确实在我的$ PATH中。
Michael McGowan

抱歉,我没有注意到Windows数据目录。我将添加一个不同的答案。
RolandoMySQLDBA 2011年

1

您没有说您有多少RAM?我认为它至少为32GB。

innodb_buffer_pool_size-23G

足够多的RAM。

query_cache_size = 1G

太大了。大时效率低下。推荐不超过50M。

key-buffer_size = 5G

在Windows上可能会有4G的硬限制(仍然),而有4G的硬限制。您的5G可能已变成1G。无论如何,如果您所有的表都是InnoDB,为什么要浪费内存。将其设置为50M。

由于错误消息正好是1G,因此闻起来像sort_buffer_size。32M可能是合理的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.