异常 ORA-08103: 使用 Hibernate 的 setfetchsize 时对象不再存在

Posted

技术标签:

【中文标题】异常 ORA-08103: 使用 Hibernate 的 setfetchsize 时对象不再存在【英文标题】:Exception ORA-08103: object no longer exists on using setfetchsize of Hibernate 【发布时间】:2013-09-15 20:36:58 【问题描述】:

我正在使用休眠。我需要获取大约 1000000 条记录,这会导致超时异常。所以我将setfetchsize 用于 6000 条记录,以便它将操作分配到每个 6000 条记录的多个事务中。

提取全部大约需要 21 小时。

但同时检索记录,如果有人删除要获取的记录之一,那么我会得到ORA-08103: object no longer exists

现在我想跳过检索时删除的对象。我该怎么做?

【问题讨论】:

不知道你要做什么的上下文,但是为什么你必须使用hibernate,并且没有直接的sql或pl/sql调用。会快得多。 我不能替换 Hibernate,因为它会花费更高的项目时间消耗。我的问题是在执行 executeQuery oracle 时会抛出 ORA-08103: object no longer exists 异常,因为有人删除了我的记录正在使用 executeQuery 获取。现在,当我获取记录时,我无法阻止任何人删除一行,所以我想要一些技术,它会导致 oracle 不会为已删除的记录抛出异常它应该跳过该记录并继续下一个记录。 @Prashant 。 . .为什么要向应用程序中提取一百万行?在我看来,有机会在数据库中进行额外的处理,节省大量时间。 【参考方案1】:

经过一周的努力,我终于解决了这个问题:

解决方案:游标很可能是基于全局临时表 (GTT) 打开的,该临时表是使用 ON COMMIT DELETE ROWS 选项创建的。 ORA-08103:对象不再存在错误的原因是紧跟在删除语句之后的提交语句。 DBA 团队不同意将 GTT 更改为提交保留行,所以最后我在 Java 服务层中添加了代码库[实现 Spring - 程序化事务]

package com.test;

import java.util.List;
import javax.sql.DataSource;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

public class StudentJDBCTemplate implements StudentDAO 
   private DataSource dataSource;
   private JdbcTemplate jdbcTemplateObject;
   private PlatformTransactionManager transactionManager;

   public void setDataSource(DataSource dataSource) 
      this.dataSource = dataSource;
      this.jdbcTemplateObject = new JdbcTemplate(dataSource);
   
   public void setTransactionManager(PlatformTransactionManager transactionManager) 
      this.transactionManager = transactionManager;
   
   public void create(String name, Integer age, Integer marks, Integer year)
      TransactionDefinition def = new DefaultTransactionDefinition();
      TransactionStatus status = transactionManager.getTransaction(def);

      try 
         String SQL1 = "insert into Student (name, age) values (?, ?)";
         jdbcTemplateObject.update( SQL1, name, age);

         // Get the latest student id to be used in Marks table
         String SQL2 = "select max(id) from Student";
         int sid = jdbcTemplateObject.queryForInt( SQL2 );

         String SQL3 = "insert into Marks(sid, marks, year) " + "values (?, ?, ?)";
         jdbcTemplateObject.update( SQL3, sid, marks, year);

         System.out.println("Created Name = " + name + ", Age = " + age);
         transactionManager.commit(status);
       
      catch (DataAccessException e) 
         System.out.println("Error in creating record, rolling back");
         transactionManager.rollback(status);
         throw e;
      
      return;
   
   public List<StudentMarks> listStudents() 
      String SQL = "select * from Student, Marks where Student.id=Marks.sid";
      List <StudentMarks> studentMarks = jdbcTemplateObject.query(SQL, 
         new StudentMarksMapper());

      return studentMarks;
   

【讨论】:

【参考方案2】:

游标很可能是基于使用ON COMMIT DELETE ROWS 选项创建的全局临时表(GTT) 打开的。 ORA-08103: object no longer exists 错误的原因是 commit 语句紧跟在 delete 语句之后。这是一个简单的例子:

 SQL> declare
  2    type t_recs is table of number;
  3    l_cur sys_refcursor;    -- our cursor
  4    l_rec t_recs; 
  5  
  6  begin
  7  
  8    -- populating a global temporary table GTT1 with sample data  
  9    insert into GTT1(col)
 10      select level
 11        from dual
 12     connect by level <= 1000;
 13  
 14   open l_cur         -- open a cursor based on data from GTT1
 15    for select col
 16          from GTT1;
 17  
 18    -- here goes delete statement
 19    -- and
 20    commit;  <-- cause of the error. After committing  all data from GTT1 will be
 21              -- deleted and when we try to fetch from the cursor
 22    loop      -- we'll face the ORA-08103 error
 23      fetch l_cur    -- attempt to fetch data which are long gone.
 24       bulk collect into l_rec;
 25      exit when l_cur%notfound;
 26    end loop;
 27  
 28  end;
 29  /


ORA-08103: object no longer exists
ORA-06512: at line 24

使用on commit preserve rows 子句重新创建全局临时表将允许安全地从基于该表的游标中获取数据,而不必担心面临ORA-08103: 错误。

【讨论】:

您认为还有其他解释吗?我已经开始从视图中将大型插入(只是一个简单的insert.. select)放入没有删除的表中。 可能另一个进程试图截断它下面的表,但“原始”表应该被锁定,这样可以防止这种情况发生。 @Ben 如果您在执行insert select 语句时截断表,是的,您将收到相同的错误,因为select 语句是游标而truncate 语句是游标一个 DDL 语句,导致双重提交 - 在截断之前和之后。 啊,当然可以;谢谢尼古拉斯。那我就得追查那个流氓进程了……

以上是关于异常 ORA-08103: 使用 Hibernate 的 setfetchsize 时对象不再存在的主要内容,如果未能解决你的问题,请参考以下文章

具有函数 ORA-08103 的 Oracle 存储过程

Oracle ORA-06512&ORA-08103对象已不存在

Oracle ORA-06512&ORA-08103对象已不存在

oracle数据库启动报错,不能启动ASM实例

Hibernate常见异常

Hibernat 原生SQL运行结果集处理方法