【问题标题】:Oracle Database Deleting Files Using JavaOracle 数据库使用 Java 删除文件
【发布时间】:2010-11-28 20:46:10
【问题描述】:

本周末的某个时候,我们的一个数据库 (11.1.0.7) 开始在通过 Java 访问部分网络上的某些文件夹时遇到问题。我已经使用一小部分java重现了这个问题,除了创建一个文件对象并尝试删除文件之外什么都不做。来自 数据库这适用于删除本地文件和删除我们 \zion\dp\ 共享上的网络文件,但不能从我们的 \zion\it\ 共享中删除。

我们有另一个在同一域用户帐户下运行的数据库,从该位置删除文件没有问题。还以服务器上的同一域用户身份登录有问题我可以在 Oracle 之外运行 java 并且删除没有问题 文件。域用户对文件夹具有完全控制权,并以我可以创建、修改和删除文件的用户身份登录。

如果我没有授予我的 oracle 数据库用户适当的 dbms_java 权限,我会收到适当的 java.security.AccessControlException 错误。在我授予java运行完成的权限后,delete命令返回false(没有删除)并且文件没有被删除。

我向 Oracle 开了一个案例,但看起来它们不再有帮助,因为它涉及从 java 层运行的文件命令,即使它只能从 Oracle 环境中重现。

测试代码:

import java.io.*;               
import java.sql.*;                 
import java.util.*;             

public class Ajclass
{
   public static void ajprocedure(String pdfFileName) throws Exception
   {
      boolean result;
      try {
         System.out.println("Start!");

         File file = new File(pdfFileName);
         //result = file.delete();
         result = file.exists();
         if (result == true) 
           System.out.println("xxFile deleted.");
         else
           System.out.println("xxFile NOT deleted!");
         System.out.println("End!");
      } catch ( Exception e ) {
         throw(e);
      }         
   }
}

我最近发现仅针对此共享且仅在从该数据库内部运行时才会失败的其他代码:

import java.io.*;
import java.sql.*;

public class DirectoryListing
{
public static void getList(String directory) throws SQLException
   {
      File path = new File( directory );
      String[] list = path.list();
      String element;
      int CurrentFile;

      for(CurrentFile = 0; CurrentFile < list.length; CurrentFile++)
      {
        element = list[CurrentFile];
        #sql { INSERT INTO DIRECTORYLISTING (FILENAME) VALUES (:element) };
      }
   }
}

【问题讨论】:

  • 删除只是一个测试。真正的处理将一个带有值的 pdf 和另一个 pdf 合并以写出一个新的 pdf。

标签: java oracle windows-server-2008 oracle11g


【解决方案1】:

从数据库内部针对操作系统运行的命令以oracle 帐户运行。因此,您需要在操作系统级别向oracle 授予对 \zion\it\ 的读写权限,并授予数据库内的 Java 权限。

删除文件是您真正想要做的吗?或者它只是一个测试?因为我们可以使用 PL/SQL 过程 UTL_FILE.FREMOVE() 删除文件。

【讨论】:

  • 你是对的,我们已经这样做了。数据库服务在对所有相关网络位置具有完全控制权的域帐户下运行。以该用户身份登录到数据库服务器,我可以对网络位置执行任何文件操作,并且在域帐户(但在 Oracle 之外)下的服务器上运行的 java 代码也可以正常工作。只有在数据库内部运行的 java 有问题。
  • 那么您的 \zion\dp\ 份额与您的 \zion\it\ 份额有什么区别?或者,周末发生了什么?
  • +1 好问题。我一直试图自己弄清楚这一点。我无法找到发生的任何事情或发生的任何变化。
【解决方案2】:

如果您有 oracle 管理员权限,请检查您的远程服务器(其他域服务器)主机名和端口在 Oracle 侦听器列表下是否可用?? (使用 Oracle Netmanager)并检查 listener.ora 文件..

【讨论】:

  • 我确实拥有 Oracle 管理员权限,但我不明白为什么我什至需要另一台机器的侦听器。
【解决方案3】:

"但是创建一个文件对象并尝试删除该文件" 你能确定删除是否失败是因为 a) 找不到文件 文件名有些奇怪 b)文件被另一个进程锁定/打开 可能有一些东西正在查看该共享(复制、备份、病毒扫描) c) 权限不足

什么是底层文件系统?

【讨论】:

  • 文件系统都是 Windows 机器上的 NTFS。在我的测试中,文件名是 x.txt 和 y.txt。这些文件由登录 oracle 服务的域用户创建。我认为我们可以排除奇怪的名称和文件锁定,因为另一个 Oracle 服务器可以删除 Oracle 之外的相同文件和 java。权限可能是个问题,但使用的是同一个域用户,所以只留下 Oracle 权限。存在相同的授权,所以我不确定要查看哪些其他权限。
  • 代码只是尝试删除还是检查文件是否存在且可写? (就像java2s.com/Code/Java/File-Input-Output/… 的代码)如果它没有引发Oracle 异常,我看不出它是Oracle 权限问题。也许一些奇怪的优化不一定立即创建文件
  • 代码只是删除。我单独进行了存在检查来代替删除。我在运行应用程序之前自己创建了文件。我将其创建为数据库服务使用的域用户。
【解决方案4】:

如何发布整个代码块。另一个论坛建议您可能无法使用相同的文件句柄。 “但我敢打赌,您正试图根据 FileOutputStream 的变量 'handle' 删除文件。如果是这种情况,您不能;您需要使用名称创建一个文件对象创建 FileOutputStream 时使用的文件,然后 delete() 那个。"

它在某些情况下有效的事实可能是“运气”而不是记录在案的行为。

PS。使用 path 的删除方法而不是文件看起来像失败会提供更多信息。

【讨论】:

  • 我根本不使用 FileOutputStream。幸运的是它在过去 10 年里一直在工作,并且仍然可以在其他数据库中工作,并且即使在同一台服务器上,仍然可以针对其他共享数据库在该数据库上工作?不是我对运气的定义。不过,您发布代码的建议很好。
  • 也许运气不是正确的选择。更多未记录的、意外的、不受支持的副作用已不再有效,可能是由于应用了补丁。也就是说,代码看起来很明确。从 microsoft 寻找 Filemon 并在 Windows 机器上运行它。也许有一个 AV 检查器或索引服务会锁定文件一段时间。
  • +1 好主意。我不认为有任何东西可以锁定我每次尝试应用程序时创建的文件,但是当我在 Oracle 之外运行 java 时会成功,但检查一下也无妨。
【解决方案5】:

Oracle 支持建议在执行删除/存在操作时查看进程监视器在 oracle 可执行文件上运行的结果后重新启动服务器。他们发现该操作从远程服务器获得了STATUS_USER_SESSION_DELETED (0xC0000203) 的结果,这意味着本地和远程服务器之间的通信在 Windows 级别上无法正常工作。我们计划在本周末重新开始,看看是否能解决问题。

【讨论】:

  • 重启盒子解决了这个问题。如果我有更大的维护窗口,我会尝试重新启动数据库,但由于不相关的原因需要完全重新启动,所以我没有花时间测试这个潜在的解决方案。
猜你喜欢
  • 1970-01-01
  • 2015-07-13
  • 1970-01-01
  • 1970-01-01
  • 2016-10-01
  • 2018-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多