我打算在Oracle或SQL-Server,Mysql等关系数据库中编写一个并行更新或导入大量数据的程序。
以下是Java中每个并行线程中的执行代码模型:
statement.setAutoCommit(false);
//a batch of DML
statement.executeBatch();
statement.commit();
持久性到磁盘的位置在上面的代码模型中发生了什么?在执行批量DML期间 - executeBatch()
,或在批量提交期间 - conn.commit()
?
关注:这两个阶段的实施可能已经同时进行。如果是这样,并行实现此程序可能没什么大意义,因为executeBatch()
和commit()
可能已占用非常宽的I / O带宽。
这个问题可能取决于数据库之间的实现,但我仍然认为,至少在那些流行的数据库中,实现是类似的。
答案 0 :(得分:0)
我可以为Oracle SQL回答这个问题,但正如其他人所指出的那样,其他RDBMS可能会有所不同。
批处理允许在发送到数据库之前批量处理多个语句 - 这是为了最小化网络开销,与持久性无关。
当您致电Statement.executeBatch()
时,之前存储的语句(使用addBatch()
)将被发送到数据库。
此时,数据库将在事务中登记这些语句并将它们写入重做日志缓冲区。由于您已禁用自动提交,因此不会立即提交。在您发出提交时,重做日志缓冲区将刷新到磁盘(在重做日志中),使事务永久化。但是,DB may decide to flush the buffer sooner - 日志写入器进程管理缓冲区以优化I / O,因此当您发出提交时,提交本身可能只需要写入磁盘。对实际数据文件的更改由数据库保存在内存缓存中 - 这可以在以后由后台任务写回磁盘,因为它对于数据完整性并不重要,并且确切地说,当这发生时取决于其他因素,包括其他用户是否正在访问同一个表中的连续行。
我应该强调所有这些,RDBMS是高度优化的系统,旨在实现高度并行和可扩展 - 如果在这方面存在性能问题,它更可能是DBA关注的问题,而不是应用程序员。