实现细节
可用内存阈值
在对临时数据库执行更新操作时,事务中途可能会出现内存不足的情况,此时事务很可能无法回滚。为解决此问题,在 C++ API 中使用了 McoSqlEngineopen() 调用中设置传递的 Database::Parameter sqlWorkspaceLimit 参数来管理此内存限制。例如:
parameters.sqlWorkspaceLimit = 2 * 1024*1024;
...
db.open("quotadb", parameters, devs);
请注意,sqlWorkspaceLimit 的默认值为 0,这意味着内存不受限。
Java 垃圾回收
Java 垃圾回收器并非总能及时释放对象,以便其他数据库操作得以执行,这可能会导致不必要的内存消耗。为避免内存消耗,建议在查询完成后尽快调用 SqlResultSet 的 close() 方法,以显式释放结果集占用的资源。
通常建议在任何长时间处理的循环中显式调用 SqlResultSet 方法 close() 和 release(),因为 Java 垃圾回收器可能会为了提高性能而保留未释放的对象。
事务管理
虽然 C++ API 默认使用隐式事务,即每次调用 executeStatement() 或 executeQuery() 时内部都会执行事务的开始和提交操作,但 Java 应用程序需要执行显式的事务控制。这通过显式地开始和提交(或回滚)事务来实现,如下面的代码片段所示:
SqlLocalConnection con = db.connectSql();
con.startTransaction(Database.TransactionType.ReadWrite);
con.executeStatement("insert into MyTable (pk,value) values (?,?)", 2012, "Good bye");
con.executeStatement("insert into MyTable (pk,value) values (?,?)", 2013, "Hello");
con.commitTransaction();
还请注意,您可以在事务仍处于打开状态时使用 Connection::checkpointTransaction() 方法来更新索引,并使对象对查询可见。
使用 Java SqlAggregator
SqlAggregator 类的作用类似于分布式连接,但仅在一个进程中运行。
要使用 SqlAggregator,Java 应用程序需创建一个 SqlLocalConnection 对象数组作为分片运行。然后启动所有 SqlLocalConnection 对象,并将该数组传递给 SqlAggregator 构造函数。例如:
SqlLocalConnection [] shards = new SqlLocalConnection[NSHARDS];
for (int i = 0; i < NSHARDS; i++)
{
shards[i] = create_database("aggg" + Integer.toString(i), config, is_dptr);
}
SqlAggregator agg = new SqlAggregator(shards, 64*1024);
一旦聚合器创建并初始化完成,即可像使用 SqlLocalConnection 一样使用它。例如,执行查询:
agg.executeStatement("1:insert into MyTable (pk,value) values (?,?)", 2012, "Good bye"));
当不再需要时,必须通过 SqlAgregator.disconnect() 方法关闭聚合器,然后关闭 SqlLocalConnection 对象:
agg.disconnect();
for (int i = 0; i < NSHARDS; i++)
{
shards[i].disconnect();
}
SQL 字符串长度
对于 SqlLocalConnection 类的 executeStatement() 和 executeQuery() 方法,语句字符串参数的长度没有限制,但对于 SqlRemoteConnection 类,语句字符串的长度受传递给构造函数的 bufferSize 参数限制,默认值为 64 Kb。(这同样适用于 SqlAggregator 类)。更多详情请参阅 SQL 语句字符串页面。