【发布时间】:2012-03-19 16:32:06
【问题描述】:
我有一个问题,需要一些启发..
我正在使用触发器来检测对我的数据库所做的更改,这意味着我为我的所有表设置了插入、更新和删除触发器 (MySQL)
然后我将该更改写入我专门制作的表格中,以包含有关更改的所有信息。我们将其命名为 xtable。 (此表不带触发器)
我的 Java 程序需要不断读取该 xtable 以让其他应用程序知道更改。
问题是,当我循环读取 xtable 时,我只能读取与数据库建立连接时的 xtable 初始值。 (连接在循环外建立)
如果对数据库进行了更改,这将导致 xtable 中的新行,则无论我通过执行“select * from xtable”查询读取多少次,都不会检测到由触发器生成的新行..
代码如下:
public static void main(String[] args) {
Connection conn = null;
try {
conn = database.getConnection();
Statement state = conn.createStatement();
String query = "select * from `xtable`;";
while (true) {
ResultSet rs = state.executeQuery(query);
while(rs.next){
// Some code for letting the other application know of the change
}
}
} catch (SQLException ex) {
} finally {
if (conn != null) {
conn.close();
}
}
}
所以基本上如果我在 xtable 为空时运行程序,我总是会获得一个空的 ResultSet,即使有时之后有新行。
其实这个问题可以通过在循环内部建立连接来解决,但是这会导致另一个问题,因为随着循环的进行,它会消耗越来越多的资源。 (我已经尝试过了,有时即使我已经正确关闭它,它最终也会使用我计算机上的所有资源)
那么谁能给我一些建议怎么办?
这是我第一次在这里发问题,如果有一些我不遵守的规则,我很抱歉,请给我正确的方向。
【问题讨论】:
-
这是一个非常糟糕的设计。考虑改用zeromq发布/订阅等消息队列系统。
-
在内部 while 循环之后关闭 ResultSet。确保您的 Connection 使用 Connection.TRANSACTION_READ_COMMITTED 隔离级别,并像这样创建您的语句: state = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
-
确保导致触发的代码是自动提交或者您明确提交了插入/更新。
-
@JimGarrison 你的意思是糟糕的设计你能更具体吗?这是否意味着我不应该使用触发器?如果不使用触发器,我应该如何检测数据库的变化?
-
@brettw 嘿,我只是试试你的建议,现在它奏效了!我认为问题是我没有指定任何事务隔离,然后默认情况下在这里可能不会发生幻读。我怀疑设置了范围锁,但我仍然不明白为什么如果是这种情况,触发器仍然可以写入表。感谢您的回答。如果可能的话,请向我解释正确的解释:)
标签: java mysql loops triggers database-connection