MySQL InnoDB挂起等待表级锁

我有一个很大的生产网络应用程序(Glassfish 3.1 + MySQL 5.5)。 所有表都是InnoDB。 每隔几天应用程序完全挂起。 SHOW FULL PROCESSLIST在不同的表上显示了许多简单的插入或更新查询,但都具有状态

等待表级锁定

例子:

 update user
set user.hasnewmessages = NAME_CONST('in_flag',_binary'\0' COLLATE 'binary') where user.id = NAME_CONST('in_uid',66381) insert into exchanges_itempacks set packid = NAME_CONST('in_packId',332149), type = NAME_CONST('in_type',1), itemid = NAME_CONST('in_itemId',23710872)

具有最长“时间”的查询也在等待表级锁定。 请帮助弄清楚为什么MySQL试图获得级别锁定以及可以锁定所有这些表的内容。 关于InnoDB锁定的所有文章都说如果不强制它,这个引擎就不使用表锁定。

我的my.cnf有这个:

 innodb_flush_log_at_trx_commit = 0 innodb_support_xa = 0 innodb_locks_unsafe_for_binlog = 1 innodb_autoinc_lock_mode=2 

二进制日志已关闭。 我根本没有“LOCK TABLES”或其他显式锁定命令。 交易是READ_UNCOMMITED

SHOW ENGINE INNODB STATUS输出: http : SHOW ENGINE INNODB STATUSSHOW ENGINE INNODB STATUS

在您的应用程序仍在访问数据库时,您是否正在使用MSQLDump来备份数据库? 这可能会导致这种行为。

我认为有些情况下MySQL会进行全表锁(即使用auto-inc)。 我找到了一个可以帮到你的链接: http : //mysqldatabaseadministration.blogspot.com/2007/06/innodb-table-locks.html

还要检查具有所有con的提交/回滚和关闭的java持久性代码。 (总是在最终块中关闭。)

尝试在MySQL配置中设置innodb_table_locks=0http://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html#sysvar_innodb_table_locks

只是一些想法……

我看到你很难在代码中使用NAME_CONST。 尽量不要使用它。 你知道,mysql有时会出错(我也发现了几个bug),所以我建议不要依赖那些不常见/经过充分测试的function。 它与列名相关,所以它可能会锁定某些东西吗? 那么它不应该只影响结果,但谁知道呢? 这是可疑的。 而且,这被标记为仅供内部使用的function。

这可能看起来很简单,但是你没有长时间运行的select语句可能会锁定更新和插入? 没有查询实际上正在运行而没有锁定?

您是否考虑过使用MyISAM而不是InnoDB?

如果您没有使用任何交易function,MyISAM可能会更有意义。 它更简单,更易于优化,并且由于它没有复杂的事务function,因此更易于在my.cnf中进行配置。

此外,根据应用程序创建的数据库负载类型,MyISAM可能更合适。 我更喜欢MyISAM用于重读应用程序,它更容易配置和理解。

其他建议:

  • 找到一种不在SQL中使用NAME_CONST的方法可能是个好主意。 “这个function是在MySQL 5.0.12中添加的。它仅供内部使用。” 当开源产品的文档说明这一点时,注意它的建议可能是一个好主意。

  • 默认情况下,MySQL将所有InnoDB表和模式数据存储在一个巨大的文件中,在该特定文件上可能存在某种操作系统级锁定 ,该文件传播到MySQL以阻止所有表访问。 通过使用innodb_file_per_table选项,您可以消除该潜在问题。 这也使MySQL更节省空间。

在这种情况下,你必须创建几个不同的数据库表,彼此相同的列,并且不要在每个表中插入超过3000行,在这种情况下,如果要在表中输入更多数据,则必须创建另一个动态表(使用生成表生成表)代码)并将新数据插入此表并从该表访问数据。 在你的情况下,如果必须生成越来越多的表,那么你必须创建新的数据库。

我认为这个技巧将帮助您更仔细地设计数据库并解决错误。