【问题标题】:Data is not properly stored to hsqldb when using pooled data source by dbcpdbcp 使用池数据源时,数据未正确存储到 hsqldb
【发布时间】:2013-06-03 01:10:42
【问题描述】:

我正在使用 hsqldb 创建缓存表和索引表。 存储的数据频率很高,所以我需要使用连接池。 另外因为有很多数据,我不会在每次提交时调用检查点,而是希望在插入 50,000 行后刷新数据。 所以问题是我可以看到 .data 文件正在增长,但是当我连接到 hsqldb 客户端时,我看不到表和数据。 所以我有 2 个简单的测试,一个插入单行,一个插入 60,000 行到新表。在这两种情况下,我都无法在任何 hsqldb 客户端中看到结果。 (注意我使用的是shutdown=true) 因此,当我在每次提交后添加检查点时,它就解决了问题。 此外,如果在连接字符串中指定使用日志,它可以解决问题(虽然我不希望在生产中使用日志)。也没有使用池连接解决了这个问题,最后是使用池数据源并在关闭之前显式关闭它。

所以我猜想连接池中的某些连接没有被关闭,从而阻止数据库以某种方式提交更改并使它们可用于客户端。但是,为什么即使有 60,000 行我也看不到结果呢? 我也希望游泳池会自动关闭...... 我究竟做错了什么?幕后发生了什么?

获取数据源的代码如下:

Class.forName("org.hsqldb.jdbcDriver");
String url = "jdbc:hsqldb:" + m_dbRoot + dbName + "/db" + ";hsqldb.log_data=false;shutdown=true;hsqldb.nio_data_file=false";
ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(url, user, password);
GenericObjectPool connectionPool = new GenericObjectPool();
KeyedObjectPoolFactory stmtPool = new GenericKeyedObjectPoolFactory(null);
new PoolableConnectionFactory(connectionFactory, connectionPool, stmtPool, null, false, true);
DataSource ds = new PoolingDataSource(connectionPool);

我正在使用这个池化数据源来创建表:

Connection c = m_dataSource.getConnection();
Statement st = c.createStatement();
String script = String.format("CREATE CACHED TABLE IF NOT EXISTS %s (id %s NOT NULL, entity %s NOT NULL, PRIMARY KEY (id));", m_tableName, m_idGenerator.getIdType(), TABLE_ENTITY_TYPE);
st.execute(script);
c.close;
st.close();

并插入行:

Connection c = m_dataSource.getConnection();
c.setAutoCommit(false);
Statement  stmt = c.prepareStatement(m_sqlInsert);
stmt.setObject(1, id);
stmt.setBinaryStream(2, Serializer.Helper.serialize(m_serializer, entity));
stmt.executeUpdate();
stmt.close();
stmt = null;
c.commit();
c.close();
stmt.close();

所以上面似乎添加了数据,但看不到。 当我明确调用 连接池.close(); 然后,只有这样我才能看到结果。 我也尝试使用 JDBCDataSource 并且效果也很好。 那么发生了什么?这样做的正确方法是什么?

【问题讨论】:

    标签: datasource connection-pooling hsqldb apache-commons-dbcp


    【解决方案1】:

    您从应用程序进程外部访问数据库的方法完全是错误的。

    只有一个 java 进程应该连接到该文件:database.

    为了实现您的目标,请在您的应用程序中启动一个 HSQLDB 服务器,使用完全相同的 JDBC URL。然后从外部客户端连接到这个服务器。

    查看指南:

    http://www.hsqldb.org/doc/2.0/guide/listeners-chapt.html#lsc_app_start

    更新:OP 评论说在应用程序停止后使用了外部客户端。因为您已使用 hsqldb.log_data=false 关闭了日志,所以不会永久保留任何内容。当您的应用程序完成其工作时,您需要执行显式 CHECKPOINT 或 SHUTDOWN。即使没有连接池,您也不能完全依赖 shutdown=true。

    查看指南:

    http://www.hsqldb.org/doc/2.0/guide/deployment-chapt.html#dec_bulk_operations

    【讨论】:

    • 只有在我的 java 应用程序停止后才连接外部客户端,因此只有一个 java 进程连接数据库。
    • 谢谢,仍然......那么为什么当我使用非池连接时一切正常(使用 log=false 并且没有明确的检查点)?文档还说每 50000 行都会自动提交,但这也没有发生。
    • 它并不是说每 50000 行都被提交。这个数字是缓存中存储的默认行数。当 50 MB 数据写入 .log 文件时会发生自动检查点,但您已禁用该日志。 shutdown=true 基本上是一种保险机制,而不是正确的关机方式。
    • 好的,那么在我的用例中,您建议何时以及如何调用检查点?也许我的方法一开始就不正确?
    • 完成插入后调用 CHECKPOINT 或 SHUTDOWN。这一切都在指南中。
    猜你喜欢
    • 2014-08-02
    • 2021-08-10
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 2013-12-17
    • 2021-11-07
    • 2010-12-26
    相关资源
    最近更新 更多