使用 ArrayBinding 在 Oracle 上插入 table 时客户端应用程序挂起
Client application hangs when inserting into table on Oracle using ArrayBinding
这是我们的环境:
.网络版本:4.5
数据库:Oracle 12.1.0.2 (odp.net)
我们正在使用 LLBL "Adapter",但我认为这与问题无关
LLBLGen 专业版:4.1
Llbl Gen Pro 运行时:4.1.13.1213
当我们执行插入时(总是插入到我们短期使用然后删除的不同表中),我们使用以下代码:
int numRecords = strings.Count();
var insertCmd = "insert into " + tableName + " (StringField) values (:StringField)";
var oracleCommand = new OracleCommand();
oracleCommand.CommandText = insertCmd;
oracleCommand.CommandType = CommandType.Text;
oracleCommand.BindByName = true;
oracleCommand.ArrayBindCount = numRecords;
oracleCommand.Parameters.Add(":StringField", OracleDbType.NVarchar2, strings.ToArray(), ParameterDirection.Input);
// this is an LLBL adapter. Like I said, I think the issue is below the LLBL layer.
this.adapter.ExecuteActionQuery(new ActionQuery(oracleCommand));
当数据库受到多个并行插入的严重打击时,我们会收到以下错误,并且从未从数据库中调用插入 returns。
- WG_6.Index_586.TVD: 在执行操作查询期间捕获到异常:ORA-24381: 数组 DML
中的错误
ORA-12592: TNS:bad 数据包
ORA-12592: TNS:bad 数据包
ORA-12592: TNS:bad 数据包
ORA-12592: TNS:bad 数据包
ORA-03111: 在通信通道上收到中断
ORA-03111: 在通信通道上收到中断
ORA-03111: 在通信通道上收到中断
在数据库上,使用 Toad 的会话浏览器,我可以看到 "Current Statement" 是正确的。
插入 schemaX.tableY(StringField) 值(:Stringfield)
在 Toad 的“等待”选项卡下,有以下消息:
“正在等待 SQL*来自客户端的净更多数据 - 到目前为止已等待 X 百秒”并且 X 不断递增,直到我们达到数据库超时。
我们尝试了 100 万个批次,这为我们的场景提供了最佳性能。然而,这个悬而未决的问题出现了。然后我将 ArrayBindCount 减少到 500K、100K、50K、10K,然后是 5K。只有当我使用 5K 时它才停止发生。
一些注意事项:
当数据库与客户端位于不同的物理机器上时,这种情况会更频繁地发生。使用本地 VM 时,这种情况很少发生。我们使用的网络通常非常可靠,没有其他值得注意的问题。
从错误消息(ORA-12592: TNS:bad packet)来看,问题似乎出在客户端,可能与"Oracle.DataAccess.Client"( ODAC).dll.
我接下来的故障排除步骤是使用 Reflector 调试来自 ODAC 代码的调用,并在强制发生此错误的同时获得更可靠的客户端跟踪。
我在尝试使用 ArrayBinding 插入 Oracle table 时遇到了同样的情况。
为 oracleCommand.ArrayBindCount 使用较小的数字似乎可以改善错误的频率(与您的一样),但不能完全改善。
解决方案是使用托管数据访问。我建议您获取最新的 ODP.NET,添加对 ManagedDataAccess 的引用并更改为:
使用 Oracle.ManagedDataAccess.Client;
使用 Oracle.ManagedDataAccess.Types;
这个问题在我的案例中已解决,无需更改代码中的任何内容。
这是我们的环境:
.网络版本:4.5
数据库:Oracle 12.1.0.2 (odp.net)
我们正在使用 LLBL "Adapter",但我认为这与问题无关
LLBLGen 专业版:4.1
Llbl Gen Pro 运行时:4.1.13.1213
当我们执行插入时(总是插入到我们短期使用然后删除的不同表中),我们使用以下代码:
int numRecords = strings.Count();
var insertCmd = "insert into " + tableName + " (StringField) values (:StringField)";
var oracleCommand = new OracleCommand();
oracleCommand.CommandText = insertCmd;
oracleCommand.CommandType = CommandType.Text;
oracleCommand.BindByName = true;
oracleCommand.ArrayBindCount = numRecords;
oracleCommand.Parameters.Add(":StringField", OracleDbType.NVarchar2, strings.ToArray(), ParameterDirection.Input);
// this is an LLBL adapter. Like I said, I think the issue is below the LLBL layer.
this.adapter.ExecuteActionQuery(new ActionQuery(oracleCommand));
当数据库受到多个并行插入的严重打击时,我们会收到以下错误,并且从未从数据库中调用插入 returns。
- WG_6.Index_586.TVD: 在执行操作查询期间捕获到异常:ORA-24381: 数组 DML 中的错误
ORA-12592: TNS:bad 数据包
ORA-12592: TNS:bad 数据包
ORA-12592: TNS:bad 数据包
ORA-12592: TNS:bad 数据包
ORA-03111: 在通信通道上收到中断
ORA-03111: 在通信通道上收到中断
ORA-03111: 在通信通道上收到中断
在数据库上,使用 Toad 的会话浏览器,我可以看到 "Current Statement" 是正确的。 插入 schemaX.tableY(StringField) 值(:Stringfield)
在 Toad 的“等待”选项卡下,有以下消息: “正在等待 SQL*来自客户端的净更多数据 - 到目前为止已等待 X 百秒”并且 X 不断递增,直到我们达到数据库超时。
我们尝试了 100 万个批次,这为我们的场景提供了最佳性能。然而,这个悬而未决的问题出现了。然后我将 ArrayBindCount 减少到 500K、100K、50K、10K,然后是 5K。只有当我使用 5K 时它才停止发生。
一些注意事项:
当数据库与客户端位于不同的物理机器上时,这种情况会更频繁地发生。使用本地 VM 时,这种情况很少发生。我们使用的网络通常非常可靠,没有其他值得注意的问题。
从错误消息(ORA-12592: TNS:bad packet)来看,问题似乎出在客户端,可能与"Oracle.DataAccess.Client"( ODAC).dll.
我接下来的故障排除步骤是使用 Reflector 调试来自 ODAC 代码的调用,并在强制发生此错误的同时获得更可靠的客户端跟踪。
我在尝试使用 ArrayBinding 插入 Oracle table 时遇到了同样的情况。
为 oracleCommand.ArrayBindCount 使用较小的数字似乎可以改善错误的频率(与您的一样),但不能完全改善。 解决方案是使用托管数据访问。我建议您获取最新的 ODP.NET,添加对 ManagedDataAccess 的引用并更改为:
使用 Oracle.ManagedDataAccess.Client;
使用 Oracle.ManagedDataAccess.Types;
这个问题在我的案例中已解决,无需更改代码中的任何内容。