ser*_*hym 5 c# t-sql oledb sql-server-2008 task-parallel-library
发现OleDBConnection似乎不是ThreadSafe.它似乎尝试打开多个连接.
//doesn't work
using (OleDbConnection oConn = TheDataAccessLayer.GetConnection())
using (OleDbTransaction oTran = oConn.BeginTransaction())
Parallel.ForEach(ORMObjects, (ORMObject, State) =>
{
if (!State.ShouldExitCurrentIteration && !State.IsExceptional)
{
var Error = ORMObject.SomethingThatExecutesANonQuery(oConn,oTran)
if (Error.Number != 0)
State.Stop();
}
});
Run Code Online (Sandbox Code Playgroud)
如果我锁定了ExecuteNonQuery的连接,那么错误就会消失,但性能却会消失.
//works
using (OleDbConnection oConn = TheDataAccessLayer.GetConnection())
using (OleDbTransaction oTran = oConn.BeginTransaction())
Parallel.ForEach(ORMObjects, (ORMObject, State) =>
{
if (!State.ShouldExitCurrentIteration && !State.IsExceptional)
{
lock(oConn)
{
var Error = ORMObject.SomethingThatExecutesANonQuery(oConn,oTran)
if (Error.Number != 0)
State.Stop();
}
}
});
Run Code Online (Sandbox Code Playgroud)
假使,假设
我无法改变ORM的本质:SQL不能被批量化
业务规则要求在单个事务中执行交互
所以:
是否有更好/更有效的方法来并行化OleDb交互?
如果没有,OleDb客户端是否有可以充分利用并行性的替代方案?(也许是原生的MSSQL客户端?)
交易需要是ACID,但"耐久性"只需要在交易结束时执行.因此,在明显的SQL语句执行后,实际在后台完成,而您的事务处理其他语句时,磁盘的物理IO可能会被推迟.
因此,以串行方式发出SQL语句可能并不比同时发布它们慢得多.考虑这种情况:
当然,有些情况下DBMS的这种"自动并行性"不能很好地工作,例如当有一个WHERE条款让不同的语句触及不同磁盘上的不同分区时 - DBMS会喜欢并行化这些子句但是如果它们不能一个接一个地喂它.
无论如何,不要猜测你的性能瓶颈在哪里.改为测量它!
BTW,MARS将无法帮助您并行化您的语句 - 根据MSDN:"但请注意,MARS是根据交错而非并行执行来定义的."