문제

분할된 postgresql 테이블에서 최대 절전 모드를 통해 일괄 삽입을 위한 솔루션이 있습니까?현재 이런 오류가 뜹니다..

ERROR org.hibernate.jdbc.AbstractBatcher - Exception executing batch:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
   at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:61)
   at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46)
   at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:68)....

내가 이 링크를 찾았어 http://lists.jboss.org/pipermail/hibernate-dev/2007-October/002771.html 그런데 웹 어디에서도 이 문제가 해결되었는지, 어떻게 해결할 수 있는지 찾을 수 없습니다.

도움이 되었습니까?

해결책

hibernate.jdbc.factory_class 속성을 설정하여 사용자 정의 Batcher를 사용해 볼 수도 있습니다.최대 절전 모드가 일괄 작업의 업데이트 횟수를 확인하지 않도록 하면 문제가 해결될 수 있습니다. 사용자 정의 Batcher가 BatchingBatcher 클래스를 확장하도록 만든 다음 doExecuteBatch(...) 메서드를 다음과 같이 재정의하여 이를 달성할 수 있습니다.

    @Override
    protected void doExecuteBatch(PreparedStatement ps) throws SQLException, HibernateException {
        if ( batchSize == 0 ) {
            log.debug( "no batched statements to execute" );
        }
        else {
            if ( log.isDebugEnabled() ) {
                log.debug( "Executing batch size: " + batchSize );
            }

            try {
//              checkRowCounts( ps.executeBatch(), ps );
                ps.executeBatch();
            }
            catch (RuntimeException re) {
                log.error( "Exception executing batch: ", re );
                throw re;
            }
            finally {
                batchSize = 0;
            }

        }

    }

새 메서드는 준비된 문 실행 결과를 확인하지 않습니다.이렇게 변경하면 예상치 못한 방식으로 최대 절전 모드에 영향을 줄 수도 있고 그렇지 않을 수도 있다는 점을 명심하세요.

다른 팁

분할된 테이블에서 두 개의 트리거를 사용하거나 여기에서 @SQLInsert 주석을 사용한다고 합니다. http://www.redhat.com/f/pdf/jbw/jmlogenski_940_scaling_hibernate.pdf 21-26페이지(String 메서드를 지정하는 @SQLInsert도 언급되어 있음)

다음은 마스터에서 추가 행을 삭제하기 위한 이후 트리거의 예입니다. https://gist.github.com/copiousfreetime/59067

삽입을 위해 트리거 대신 RULES를 사용할 수 있는 경우 표시되며 올바른 숫자를 반환할 수 있지만 WHERE 문 없이 단일 RULE만 사용할 수 있습니다.

심판 1

심판 2

심판 3

또 다른 옵션은 분할된 테이블을 '래핑'하는 뷰를 생성한 다음 마스터 테이블에 원치 않는 추가 행을 실수로 추가하지 않고 새로운 행을 반환하여 성공적인 행 업데이트를 나타내는 것입니다.

create view tablename_view as select * from tablename; -- create trivial wrapping view

CREATE OR REPLACE FUNCTION partitioned_insert_trigger() -- partitioned insert trigger
RETURNS TRIGGER AS $$
BEGIN
   IF (NEW.partition_key>= 5500000000 AND
       NEW.partition_key <  6000000000) THEN
      INSERT INTO tablename_55_59 VALUES (NEW.*);
   ELSIF (NEW.partition_key >= 5000000000 AND
          NEW.partition_key <  5500000000) THEN
      INSERT INTO tablename_50_54 VALUES (NEW.*);
   ELSIF (NEW.partition_key >= 500000000 AND
          NEW.partition_key  <  1000000000) THEN
      INSERT INTO tablename_5_9 VALUES (NEW.*);
   ELSIF (NEW.partition_key >= 0 AND
          NEW.partition_key <  500000000) THEN
      INSERT INTO tablename_0_4 VALUES (NEW.*);
   ELSE
      RAISE EXCEPTION 'partition key is out of range.  Fix the trigger function';
   END IF;
   RETURN NEW; -- RETURN NEW in this case, typically you'd return NULL from this trigger, but for views we return NEW
END;
$$
LANGUAGE plpgsql;

CREATE TRIGGER insert_view_trigger
   INSTEAD OF INSERT ON tablename_view
   FOR EACH ROW EXECUTE PROCEDURE partitioned_insert_trigger(); -- create "INSTEAD OF" trigger

참조: http://www.postgresql.org/docs/9.2/static/trigger-definition.html

뷰 래퍼 경로 중 하나의 옵션은 삭제 및 업데이트를 위한 "대신" 트리거도 정의하는 것입니다. 그런 다음 모든 트랜잭션에서 일반 테이블 대신 뷰 테이블의 이름을 사용할 수 있습니다.

뷰를 사용하는 또 다른 옵션은 기본 테이블의 모든 삽입이 [트리거를 사용하는] 뷰로 이동하도록 삽입 규칙을 만드는 것입니다. partitioned_insert_trigger 위에 나열된 tablename_view 및 insert_view_trigger가 생성됨)

create RULE use_right_inserter_tablename AS
      ON INSERT TO tablename
      DO INSTEAD insert into tablename_view VALUES (NEW.*);

그런 다음 새 작업 뷰 래퍼 삽입을 사용합니다.

고맙습니다!그것은 트릭을 수행했으며 지금까지는 아무런 문제도 발생하지 않았습니다 :)....한 가지 당신은...나는 구현해야했다 BatcherFactory 수업을 듣고 그것을 persistence.xml 다음과 같은 파일 :

property name="hibernate.jdbc.factory_class" value="path.to.my.batcher.factory.implementation"

그 공장에서 위의 코드를 사용하여 Batcher 구현을 호출했습니다.

PS Hibernate Core 3.2.6 ga

다시 한번 감사합니다

많은 검색 후 최대 절전 모드를 통해 문서를 삽입하는 동안 업데이트된 행이 반환될 것으로 예상된다는 사실을 발견한 후 동일한 문제에 직면했습니다. 따라서 null 대신 트리거 프로시저에서 새 행으로 변경하면 아래와 같이 문제가 해결됩니다.

새로운 반품

같은 문제에 대한 다른 해결책을 찾았습니다 이 웹페이지에서:

이는 @rogerdpack이 말한 것과 동일한 솔루션을 제안합니다. Null 반환 에게 반품 NEW, 쿼리를 사용하여 마스터에서 중복된 튜플을 삭제하는 새 트리거를 추가합니다.

DELETE FROM ONLY master_table;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top