【发布时间】:2015-08-04 06:31:06
【问题描述】:
我有一个 J2EE 服务器,目前只运行一个线程(即使在一个请求中也会出现问题)以将其内部数据模型保存到 MySQL/INNODB 表。
基本思想是从平面文件中读取数据,进行大量计算,然后将结果写入 MySQL。第二天读取另一组平面文件并重复步骤 1。由于只有一小部分行更改,我使用已写入行的记录集,与内存中的当前结果进行比较,然后相应地更新/插入它(没有删除,只是设置一个deletedFlag)。
问题:尽管是一个纯粹的顺序过程,但我得到了锁超时错误 (#1204) 并且 Innodump 显示记录锁(虽然我不知道如何计算细节)。为了使我的 Windows 机器下的事情复杂化,一切正常,而生产系统(我无法安装 innotop)有一些记录锁。
到关键代码:
- 读取数据并计算(有效)
- 从 Tomcat 池获取连接并设置为 autocommit=false
- 使用语句发出“LOCK TABLES order WRITE”
- 按表顺序打开记录集(可更新)
- 对于 Recordset 中的每一行 --> 如果有差异,则从内存对象更新
- 对于尚未在数据库中的对象 --> 插入数据
- 提交连接,关闭连接
步骤 5/6 有一个 Commitcounter,因此每 500 次更改都会提交行(以避免有 50.000 行未提交)。在第一次运行(所以没有任何锁)这需要最大。 30秒/桌。
如上所述,我现在避免与数据库进行任何其他交互,但将来其他进程(用户请求)可能会读取数据甚至写入一些字段。我不介意这些进程读取旧/新数据并等待几分钟以将更改保存到数据库(即锁定)。
我很乐意接受任何比这更好的建议。
总结:复杂代码计算要与数据库同步的内存对象。尽管事实上它顺序锁定,但这种同步当前似乎锁定了自己,更改解锁表而没有抛出任何异常。但由于某种原因,行锁似乎仍然存在。
亲切的问候
附加信息: Mysql:show processlist 列出没有活动的连接(全部休眠或等待表顺序上的表锁),而“show engine INNODB”报告了许多行锁(不幸的是我不明白哪个事务是指输出非常神秘) .
【问题讨论】:
-
你使用的是纯 jdbc 吗?没有代码使检查变得更加困难。您是否在每次写入时都提交并关闭连接?您是否在不需要时保持连接打开?
-
抱歉这么晚才回来。我通过标准 Tomcat 连接池(通过 web.xml 中的 ressource-defs 配置)和 DataSource.getConnection 使用 JDBC。
-
不要在 InnoDB 中使用
LOCK TABLE!
标签: java mysql jdbc locking innodb