我正在尝试从非托管版本迁移到Oracle.ManagedDataAcess,并收到随机数ORA-12570 TNS:数据包读取器故障。
我不知道为什么会出现这个错误,但一旦出现,每个后续请求都会在大约10 - 30分钟内出现同样的错误,然后它又会在10 - 30分钟内出现,依此类推。
因此,这是一段时间内的随机后续失败,然后是后续成功
已经尝试了很多东西,恢复:
- 环境:**
- Oracle. ManagedDataAcess版本12.1.2400(4.121.2.20150926)(nuget)(服务器上未安装可覆盖bin版本的gac引用)
- Oracle服务器Oracle数据库12c企业版12.1.0.2.0版-64位生产
- Windows 2012(Windows更新正常)
- 已检查:**
- 防火墙:这不是防火墙的问题
- 机器错误:同样的问题发生在我的计算机、Azure WebApp和AWS EC2示例上
- 干扰:没有运行嗅探器、透明代理等。
- 加密:我不使用任何类型的加密(除非默认启用了我不知道的东西)
- 连接字符串:相同的连接字符串在非托管版本中运行良好
- 其他信息:**
- 这是一个生产数据库,非常稳定
- 应用程序编译为anycpu,IIS应用程序池限制为64位
- 我每次测试完全相同的请求(只是一个restws,webapi的geturl的刷新),所以它与数据格式无关
- 配置:**
- 服务器sqlnet.ora**
SQLNET.AUTHENTICATION_SERVICES= (NTS)
NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT)
- 应用程序Web.配置**
<connectionStrings>
<add name="XXXX" connectionString="Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=xxx.xxx.com)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=xxx)));User Id=xxxxx;Password=xxxxx;" />
</connectionStrings>
<configSections>
<section name="oracle.manageddataaccess.client" type="OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
</configSections>
<oracle.manageddataaccess.client>
<version number="*">
<dataSources>
<!--<dataSource alias="SampleDataSource" descriptor="(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL))) " />-->
</dataSources>
<settings>
<setting name="SQLNET.AUTHENTICATION_SERVICES" value="NONE"/> <!--NTS-->
<setting name="sqlnet.crypto_checksum_server" value="rejected"/>
<setting name="sqlnet.crypto_checksum_client" value="rejected"/>
<setting name="SQLNET.ENCRYPTION_SERVER" value="rejected"/>
</settings>
</version>
</oracle.manageddataaccess.client>
- 部分参考文献:**
https://community.oracle.com/thread/3634263?start=0&tstart=0
ODP.net managed driver throws ORA-12570: Network Session: Unexpected packet read error
Managed Oracle Client with Oracle Advanced Security Options
ODP.NET error in IIS: ORA-12357 Network Session End of file
- 更新1**
在池发生变化后(正如我在这里描述的答案),我决定发布一个版本来做一些真正的测试。1天后,用户抱怨性能,我得到了另一个错误:值不能为空。参数名:字节数组
我把引用改回了非托管版本,一切都恢复正常,速度更快,没有字节数组错误,池管理更好。
所以我现在只是放弃了托管版本,也许我会在Oracle的下一个版本中再次尝试。
这里有一些关于这个新错误的参考,如你所见,看起来像是另一个bug(仍然没有任何答案)。
https://community.oracle.com/thread/3676588?start=0&tstart=0
EF + ODP.NET + CLOB = Value Cannot be Null - Parameter name: byteArray?
到目前为止,不使用的理由:
- 池化管理错误
- CLOB空/非空字节数组错误
- 性能下降可能与池化错误有关
7条答案
按热度按时间taor4pac1#
根据我的经验,类似的错误12570(reader vs writer)只有一个原因--你网络上的某个东西终止了空闲的tcp连接。通常这是一个防火墙/管理交换机。你说你已经排除了防火墙,但我不确定是怎么排除的。有可能是数据库本身终止了连接(dba脚本),但我记得那是一个不同的错误。
Ora-12571可能稍有不同,但既然您已经确定了问题是相同的,因为它是长期建立的池连接,我将继续讨论。
您可以做以下几件事:
1.在连接字符串中设置最小池大小= 0。这通常可以解决我的问题。它允许在应用空闲时关闭整个池。但也有一个很小的机会,如果你的流量波动剧烈,decr池大小可能需要增加,以便更快地关闭由疯狂的匆忙创建的连接。
1.在sqlnet. ora中设置Expire_Time。名称不明显,此设置发送一个探测包,这会导致满足任何tcp空闲监视。这里唯一的问题是我不完全确定如何使用托管提供程序设置sqlnet设置。我猜sqlnet.ora可以放在exe目录中,但我也看到一些指示,表明它可以在.config中以(参见类似的wallet_override示例here)因为您只在托管提供程序中获得此设置,所以我想知道您的非托管客户机sqlnet.ora是否已经具有此设置。
多年来我已经多次看到这种情况,第一次发生时我创建了一个实用程序,通过创建不同持续时间的连接,基本上可以执行二进制搜索来确定确切的超时时间。如果它始终停留在相同的终止时间,您可以猜测是某个地方的设置导致了这种情况。如果它不稳定,那么您可能有某种基础设施故障。
不幸的是,我把它创建成了一个c#表单应用程序,所以我把表单代码和设计器代码都粘贴到了下面:
Form1.cs:
Form1.designer.cs:
ljo96ir52#
在禁用池化(Pooling=False)之后,正如@bdn02所建议的,我可以确认它工作了。但是我认为它会影响性能,我担心在没有任何池化的情况下将代码发布到生产环境中(我认为标准值是可以的)。
因此,我尝试了许多配置,看起来Oracle的池管理不知何故(不是很清楚)引发了一个ORA-12570错误,一段时间后,会话关闭,应用程序再次工作。
为了找到启用池的最佳配置,我创建了一个测试应用程序来启动50个线程(每个线程每50 ms执行一次测试),并降低默认池值,直到错误停止。这样我就能够获得一个最佳配置,稳定,没有任何错误。
显然,它并不适用于每个服务器,但这是我的最终连接字符串配置:
slmsl1lt3#
我将提供一个powershell脚本,用于检查数据库连接。
$baselogpath = "" $filesuffix = "_GetDBConnection" $dbuser ="" $dbpassword ="" $dbalias = ""; $command = new-Object Oracle.DataAccess.Client.OracleCommand($queryString, $connection); $connection.Open(); $count = $command.ExecuteScalar(); $connection.Close(); $message = "Records found: " + $count; $esito = "OK"; } Catch { $message = $_.Exception.Message; $esito = "KO"; } $now = Get-Date $filename = $baselogpath + $now.Year + $now.Month.Tostring("00") + $now.Day.Tostring("00") + $filesuffix + ".log" if (!(Test-Path($filename))) { $fileheader = "Time Esito, Elapsed, Message" $fileheader > $filename } $Time.Stop(); $Elapsed = $Time.Elapsed; $row = $now.Hour.toString("00") + ":" + $now.Minute.toString("00") + ":" + $now.Second.toString("00") + " " + $esito + "," + $Elapsed.Hours.toString("00") + ":" + $Elapsed.Minutes.toString("00") + ":" + $Elapsed.Seconds.toString("00") + "," + $message; $row >> $filename
您是否可以尝试使用Oracle托管dll的托管版本每隔一分钟调度此脚本?如果问题仅发生在Web应用程序上,或者与Oracle托管驱动程序相关,我可以理解。如果您希望进行高级测试,您可以调度此脚本的副本,该脚本使用oracle.dataaccess的非托管版本。
祝你好运
blmhpbnm4#
我在使用SQL Server Reporting Services 2016和ODAC 12c版本4时遇到了同样的间歇性错误:
将池参数
Data Source="myOracleDB";Pooling="false"
添加到SSRS中的Oracle数据源完全解决了该问题。立即重新执行报告可以正常工作。
我意识到每次创建一个新连接而不是使用池会有潜在的性能问题,但是在Oracle修复这个问题之前,我不希望我的用户遇到这个错误。
6tqwzwtp5#
我在应用程序异常中收到此错误。内部异常中没有更多有用的详细信息。更改池选项无法修复此问题,禁用池也无法修复此问题。启用跟踪后,跟踪文件中会显示另一个错误“ORA-12537 network session end of file(不传播到应用程序异常)。那个线程暗示oracle驱动程序的旧版本是罪魁祸首。我检查了一下,而且我用的是2014年的版本,升级到2017/12. 2 c/12. 2. 0. 1. 0版本解决了这个问题。
dphi5xsq6#
有KeepAlive设置,可以防止连接丢失的池错误,如ORA-12571等。(而不是禁用池)
问题和解决方案:https://github.com/oracle/dotnet-db-samples/issues/58
在打开连接之前设置
connection.KeepAlive = true;
。您还需要具有不低于2.19.100的Oracle.ManagedDataAccess.Core版本(不了解非核心应用程序)。我在生产版本中偶尔会遇到难以理解的池错误“Oracle错误ORA-12571远程主机强制关闭了现有连接”和“ORA-03135:连接失去联系”与.Net Core 3.0和设置帮助。
fruv7luv7#
多年来我一直随机收到这个错误,因为我的连接在很多方面都丢失了。
我通过使用失败后重试方法解决了这个问题:
使用上面的示例方法,您可以执行以下操作:
如果使用实体框架,则可以配置执行策略,以便在发生错误(12571、12570、03135等)时重试。
下面是实体框架核心中的一个示例:
参见:
Answer about execution extrategy
ORA 12570 on Azure