MySQL 服务器在运行 apache/php 的专用服务器上不断崩溃。我不是 MySQL 专家,所以我需要一些专家的建议。
该网站使用了 Innodb 和 MyISAM 引擎,但 Innodb 使用最为频繁。
从 WHM phpmyadmin 我发现以下红色选项
Innodb_buffer_pool_pages_dirty 18
Innodb_buffer_pool_reads 31 k
Handler_read_rnd 128 k
Handler_read_rnd_next 3,013 k
Created_tmp_disk_tables 1,534
Sort_merge_passes 10
Opened_tables 807
Table_locks_waited 8
这是 MySQL 配置
max_connections = 500
safe-show-database
skip-locking
key_buffer = 700M
max_allowed_packet = 32M
table_cache = 512
sort_buffer_size = 64M
read_buffer_size = 2M
read_rnd_buffer_size = 2M
myisam_sort_buffer_size = 128M
thread_cache_size = 16
query_cache_size= 512M
query_cache_limit=1024M
thread_concurrency = 8
connect_timeout = 8
wait_timeout = 120
interactive_timeout = 15
wait_timeout = 500
innodb_buffer_pool_size=1024M
open_files_limit = 8192
tmp_table_size = 64M
long_query_time = 1
log_slow_queries
innodb_autoinc_lock_mode = 2
set-variable = innodb_lock_wait_timeout=10
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
[isamchk]
key_buffer = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M
[myisamchk]
key_buffer = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M
错误日志
100930 9:44:12 [Warning] /usr/sbin/mysqld: Forcing close of thread 283 user: 'rdf'
100930 9:44:19 [ERROR] /usr/sbin/mysqld: Sort aborted
100930 9:44:19 [ERROR] /usr/sbin/mysqld: Sort aborted
100930 9:44:21 [ERROR] /usr/sbin/mysqld: Sort aborted
100930 9:44:53 [Warning] /usr/sbin/mysqld: Option '--set-variable' is deprecated. Use --variable-name=value instead.
100930 10:37:16 [ERROR] Cannot find or open table XXXX from
the internal data dictionary of InnoDB though the .frm file for the
table exists. Maybe you have deleted and recreated InnoDB data
files but have forgotten to delete the corresponding .frm files
of InnoDB tables, or you have moved .frm files to another database?
我看到很多错误,无法找到或打开表。我还没有接触过 MySQL 配置。
答案1
就我个人而言,我认为其中一些价值观完全不正常,但这不应该导致崩溃。
http://blog.mysqltuner.com/有一个脚本可能会给你一些调整提示,但他们建议服务器运行 48 小时以上。
当您说崩溃时,您是指 mysqld 终止还是没有响应?是系统没有响应还是只是 mysql 没有响应?检查 dmesg、/var/log/messages、核心转储等。除非出现硬件问题,否则我们假设 mysql 已锁定。您没有提到上述值的正常运行时间,也没有提到您使用的 mysql 版本,但我们会假设正常运行时间相对较短。在磁盘上创建的 tmp 表可能意味着您的临时表大小太小,或者您有无法缓存在内存中的查询。
我看到的第一件事是 table_cache 低于打开的表。这不一定是个大问题,但可能会导致大量流失。显示状态如“open_tables”;如果 table_cache 已达到上限,您可能需要增加 table_cache。
如果您使用的是较新版本的 mysql,/var/lib/mysql/hostname.err 或 /var/log/mysql/mysql.err 可能包含一些其他信息。如果您可以在事件期间执行“show processlist”,或者 mysqladmin -u root -ppassword processlist > /var/tmp/pl(如果您的服务器需要重新启动,则执行到重新启动时未清除的某个区域),您可能能够检查崩溃时发生的情况。您的 mysql slowquery 日志怎么样?Longquery 为 1 可能会创建大量额外的日志记录,但是,如果您发现查询花费了 300 多秒,而本应花费 4 秒,那么您可能知道哪个表挂了。
InnoDB 并不能解决您的所有问题。不懂 mysql 的程序员会使用 InnoDB,因为它使用行级锁定而不是表级锁定。锁定表的一小部分,您应该会看到并发性上升。这个理论是正确的,但是,使用 InnoDB 所做的事情与使用 MyISAM 的方式不同。
select count(*) from innodbtable where condition='asdf';
select count(*) from myisamtable where condition='asdf';
在第一种情况下,InnoDB 将锁定表并进行完整扫描。在第二种情况下,MyISAM 不会锁定表(如果条件包含在索引中,则会从索引中回答)。
select count(varname) from table where condition='asdf';
如果 varname 不是键,这将强制执行表扫描以确保 varname 不为空。如果 varname 是键,它仍会检查所有键值以查看是否有任何值为空。
对涉及文本字段的表进行选择会自动创建磁盘临时表 - 您可以修改查询以避免这种情况。
如果您可以发布更多有关应用程序运行的信息,包括崩溃的含义、显示变量/显示状态的输出、错误日志的内容等,我相信这里有更多知识的人可能会进一步调试它。
我猜你通过 reboot/powercycle 重启了服务器。在你的 /var/lib/mysql 目录中,应该有一些文件,例如:
ibdata1
ib_logfile0
ib_logfile1
我认为其中一个文件包含一些坏数据。
您可以在 [mysqld] 部分使用 innodb_force_recovery=4 重新启动 mysql,看看 innodb 文件是否能够修复。如果不能,请加载您的热副本或最近的转储之一。您可能无法在没有魔法的情况下删除该表,但应该能够重命名该表并从备份中重新导入。