我们最近将我们的一张表切换到了 innodb,现在我们正在经历非常缓慢的 UPDATE 执行时间。过去需要 0.010-0.030 秒的更新现在可能需要超过 70 秒。一些查询被丢弃是因为它们无法在默认的 50 秒限制内获得锁(我意识到我们可以提高这个限制)。
有问题的表只有一个索引,主键本身是一个 mediumint 值。该表有大约 100 万行。此上下文中的所有 UPDATE 都涉及单行。通常,该行中的 4-5 列在每个查询中都会受到影响。
当前的 my.cnf 粘贴在下面。您是否看到任何可能特别导致 innodb 更新性能不佳的内容?
[mysqld]
set-variable=local-infile=0
datadir=/db/mysql/data
socket=/var/lib/mysql/mysql.sock
#log = /var/log/mysqld.log
log-error = /var/log/mysqld.error.log
user=mysql
# Default to using old password format for compatibility with mysql 3.x
# clients (those using the mysqlclient10 compatibility package).
old_passwords=1
skip-locking
key_buffer = 1G
query_cache_size = 256M
thread_cache_size = 128
table_cache = 2048
max_connections = 400
query_cache_limit = 1024M
log_slow_queries = /var/log/mysql-slow.log
long_query_time = 1
skip-bdb
skip-locking
skip-name-resolve
innodb_buffer_pool_size=1G
innodb_additional_mem_pool_size=20M
innodb_flush_log_at_trx_commit=2
#innodb_log_file_size=250M
innodb_log_buffer_size=8M
innodb_lock_wait_timeout=50
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
更新:
innodb_log_file_size: 5242880
have_innodb: YES
"WHERE" 子句总是只查找一列,这是主键。
更新 - 2012 年 7 月 26 日:
我们将数据库升级到 mysql 5.5。现在 innodb 更新非常快,在我们的特定情况下不到 0.010 秒。而且,方差非常低。我对此的看法是:在 mysql 5.0 上应谨慎使用 innodb。
观点#1
当您仅在 InnoDB 中按主键更新时,聚集索引(又名gen_clust_index)可能会被锁定,这是一种罕见但可能的情况。
我曾经回答过一个人关于这个主题的三个帖子
请仔细阅读这些内容。这些问题的发布者根据看到的 InnoDB Clustered Index Locking 行为找到了自己的解决方法。可悲的是,他没有发布解决方法是什么。
此外,当您看到查询运行缓慢时,登录 mysql 并运行
SHOW ENGINE INNODB STATUS\G
并开始在聚集索引中查找锁。观点 #2
我看到你注释掉了innodb_log_file_size。默认为 5MB。由于innodb_buffer_pool_size设置为 1G,因此 innodb_log_file_size 需要为 256M。单击此处将 innodb_log_file_size 设置为 256M。
观点#3
我看到您没有使用innodb_file_per_table。您可能希望使用它来专门为具有一百万行的一个表完成表更新。单击此处查看如何清理 InnoDB 基础架构以使用 innodb_file_per_table。
您是否正在更新主键值的值?
任何列是否是其他表的外键?由于 InnoDB 还通过 CASCADE 更新同一事务中的外键。
你能否将 innodb_buffer_pool_size 增加到 1GB 以上,以便整个表可以放入内存中?
schmea 中有多少其他表 - 因为可能存在调整表空间大小以执行更新的问题
您可能想尝试使用为每个表创建表空间文件的 innodb_file_per_table。更改此参数后,您需要重新启动服务器,然后重新创建数据库以使其生效。