跨线程共享事务

时间:2013-12-26 23:43:55

标签: c# sql multithreading oracle transactions

我目前有一个C#进程,它将数百万条记录保存到Oracle,目前所有记录都在一个线程和一个事务中。我有兴趣对此进行一些并行处理,我可以跨线程分割数据。 ADO.NET/Oracle事务是否可以跨线程正常工作?我只是在主线程上创建事务,还是我还需要为每个线程创建一个子事务?

任何有关这方面的经验都可以提供一些性能改进,或者是Oracle本身的瓶颈。

2 个答案:

答案 0 :(得分:3)

如果您的代码基本上是:

for each record
    add record to database

然后添加多个线程不太可能有很大帮助。当可能能够通过两个线程获得性能提升时,一个正在收集并传输一条记录而另一条记录被插入时。但重叠的可能性不大。

你做的事情要好得多:

while not end of records
    add 1,000 records to block
    call stored proc to insert 1,000 records

这应该可以加快速度,因为你减少了客户端和服务器之间来回的数量。

加快速度的方法可能不是创建运行循环的多个线程,而是发出异步调用,以便数据库可以在创建下一个记录块时执行插入操作。像这样:

while not end of records
    add 1,000 records to block
    wait for pending asynchronous call to complete
    issue asynchronous call to insert 1,000 records

有许多不同的方法可以发出异步调用。我建议使用Tasks

修改

在我看来,尝试在异步调用中保持事务处于活动状态时可能会遇到问题。如果是这样,那么你在主线程上执行数据库插入,并让异步任务填充缓冲区。它看起来像这样:

start transaction
buffer = fill_buffer(); // this is synchronous
while buffer.count > 0
{
    task = start asynchronous task to fill the next buffer
    call database to insert records from buffer
    buffer = task.result  // waits for task to complete
}
end transaction

此技术确保事务的所有数据库调用都发生在主线程上。

答案 1 :(得分:1)

我的建议是,如果可以(您的工作场所允许),请使用批量插入而不是依赖中间件应用程序将其写为pl / sql过程。只要编码良好,改进将是巨大的。

如果你必须使用中间件(.net),我建议你使用ODP.NET Link,因为不推荐使用ADO.NET-to-Oracle(如果我没有记错的话)。此外,ODP.NET将为您提供性能提升,因为它使用了Oracle 11g的新功能和改进。

就中间件而言,我从未做过任何并行线程,但我怀疑你会遇到与oracle的交易问题(因为你正在插入和关系数据库的工作方式)。我知道这是可能的,但是为了额外的努力,将处理移动到数据库并让oracle发挥其魔力更好。