MySQL InnoDB挂起等待表级锁

时间:2011-05-31 10:02:37

标签: java mysql locking innodb

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

  

等待表级锁定

示例:

update user<br>
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://avatar-studio.ru:8080/ph/imonout.txt

6 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:1)

我认为有些情况下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

只是一些想法......

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

您是否考虑过使用MyISAM代替InnoDB?

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

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

其他建议:

  • 找到一种不在SQL 中使用NAME_CONST的方法可能是个好主意。 "This function was added in MySQL 5.0.12. It is for internal use only." 当开源产品的文档说明这一点时,注意它的建议可能是个好主意。

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

答案 5 :(得分:0)

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

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

相关问题