我有一个我编写的应用程序,它使用 OCI 连接到 Oracle 数据库。数据库最近已升级到 Oracle 18,此后应用程序中的数据库搜索随机停止工作。
我已将问题缩小到这一点。当应用程序连接到数据库时,它会运行一些ALTER SESSION
命令以在条件下禁用区分大小写LIKE
(以便我可以搜索“smith”并仍然找到“Smith”)。几个小时后,网络断开 TCP 连接。第二天早上,当有人试图访问系统时,Oracle 客户端透明地重新连接并执行查询。
问题是这种重新连接是在我的代码不知道的情况下发生的,显然是由 Oracle 客户端本身进行的,并且在重新连接后它不会重新运行原始ALTER SESSION
命令。我们的 DBA 向我提供了一个审计日志,其中显示了会话 ID 的更改、一次新的LOGON
尝试和一次ALTER SESSION
设置时区的运行(这不是来自我的代码,也出现在原始连接中)。
这意味着我的应用程序按正常方式向数据库发出查询,没有意识到有任何中断,但突然它们变得区分大小写并且用户开始抱怨搜索没有返回任何结果。
使用以前的 Oracle 服务器版本,如果断开连接,我的代码会收到错误,并且代码会尝试重新连接,并且作为重新连接的一部分,它会ALTER SESSION
再次运行命令,这样系统的行为就不会发生变化.
我找不到任何关于此自动重新连接功能或如何调整它的信息,所以有什么方法可以保留ALTER SESSION
更改以便在重新连接后重新应用它们,或者禁用此行为并向代码返回错误如果像过去那样失去连接?
客户端是较旧的 11.2 版本,升级它并不是很实用,但由于它在服务器升级之前就可以工作,所以我认为该版本没问题。
您的连接似乎已启用透明应用程序故障转移 (TAF)。如果启用 TAF,如果客户端和服务器之间的连接中断,Oracle 客户端将重新连接到数据库或备用数据库。您使用 OCI 客户端,为此可以注册一个 在客户端重新连接后调用的故障转移回调函数 。在此回调函数中,您可以发出所需的“ALTER SESSION”命令。但也许您不想使用 TAF。
所以首先 DBA 应该检查您的会话是否使用 TAF。可以在 Net Services Administrator's Guide中找到适当的查询
使用以下示例输出
FAILOVER_TYPE NONE 告诉我们,没有配置 TAF。与 NONE 不同的 FAILOVER_TYPE 告诉我们为这些会话配置了 TAF。
如果您的会话使用 TAF,那么您应该找出它的配置位置。它可以在客户端或服务器端配置。您可以检查“tnsname.ora”文件或使用“tnsping”实用程序检查您的客户端配置。如果您从Net Services Administrator's Guide中找到与此示例类似 的内容
那么 TAF 是因为配置的
FAILOVER_MODE=(TYPE=select)
。如果是这种情况,您应该在没有 TAF 的情况下配置适当的连接字符串。但是,即使没有在客户端配置 TAF,也可以在服务器端为该服务配置它。所以做下面的查询
以下示例输出显示 TAF 将用于
(SERVICE_NAME=sales.us.example.com)
即使未在客户端上配置也是如此。在这种情况下,
(SERVICE_NAME=sales.us.example.com)
即使客户端未配置 TAF,也会使用 TAF。因此,您必须使用未配置 TAF 的服务,在示例“sales3.us.example.com”中就是这样的服务。可以使用 DBMS_SERVICE 包创建服务,但在大多数情况下,它们是由一些额外的工具创建的,例如 Oracle Real Application Cluster。通过在数据库服务器上执行以下命令,可以显示 RAC 为数据库“salesdb”创建的服务
以下输出(取决于数据库版本)显示 RAC 将在数据库启动后创建 TAF 服务
您可以使用以下命令创建不带 TAF 的新服务“sales3.us.example.com”
作为解决方法,已将触发器添加到用户帐户,以便
ALTER SESSION
在每次连接时运行命令。这已经解决了问题,但是我们仍然不确定为什么会话透明地重新连接而不通知客户端应用程序!