diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/ObjectStore.java b/metastore/src/java/org/apache/hadoop/hive/metastore/ObjectStore.java index 1b14fb1..1592b24 100644 --- a/metastore/src/java/org/apache/hadoop/hive/metastore/ObjectStore.java +++ b/metastore/src/java/org/apache/hadoop/hive/metastore/ObjectStore.java @@ -461,20 +461,19 @@ public void rollbackTransaction() { debugLog("rolling back transaction: no open transactions: " + openTrasactionCalls); return; } - openTrasactionCalls = 0; debugLog("Rollback transaction, isActive: " + currentTransaction.isActive()); - if (currentTransaction.isActive() - && transactionStatus != TXN_STATUS.ROLLBACK) { - transactionStatus = TXN_STATUS.ROLLBACK; - try { - // could already be rolled back + try { + if (currentTransaction.isActive() + && transactionStatus != TXN_STATUS.ROLLBACK) { currentTransaction.rollback(); - } finally { - // remove all detached objects from the cache, since the transaction is - // being rolled back they are no longer relevant, and this prevents them - // from reattaching in future transactions - pm.evictAll(); } + } finally { + openTrasactionCalls = 0; + transactionStatus = TXN_STATUS.ROLLBACK; + // remove all detached objects from the cache, since the transaction is + // being rolled back they are no longer relevant, and this prevents them + // from reattaching in future transactions + pm.evictAll(); } } @@ -545,7 +544,7 @@ public Database getDatabase(String name) throws NoSuchObjectException { } public Database getDatabaseInternal(String name) throws MetaException, NoSuchObjectException { - return new GetDbHelper(name, null, true, true) { + return new GetDbHelper(name, null, true, true, true) { @Override protected Database getSqlResult(GetHelper ctx) throws MetaException { return directSql.getDatabase(dbName); @@ -2314,9 +2313,21 @@ private void dropPartitionsNoTxn(String dbName, String tblName, List par protected final String dbName, tblName; private boolean success = false; protected T results = null; + private boolean forceIsInTxn = false; + // Parameter that, if set, force-overrides the check for isInTxn as being true. + // Useful for cases where we know we will only ever be called from within a txn, + // but detecting if we are inside a txn can fail. See HIVE-8850 for details public GetHelper(String dbName, String tblName, boolean allowSql, boolean allowJdo) throws MetaException { + this(dbName, tblName, allowSql, allowJdo,false); + } + + public GetHelper(String dbName, String tblName, boolean allowSql, + boolean allowJdo, boolean forceIsInTxn) + throws MetaException { + + this.forceIsInTxn = forceIsInTxn; assert allowSql || allowJdo; this.allowJdo = allowJdo; this.dbName = dbName.toLowerCase(); @@ -2329,7 +2340,7 @@ public GetHelper(String dbName, String tblName, boolean allowSql, boolean allowJ this.table = null; } this.doTrace = LOG.isDebugEnabled(); - this.isInTxn = isActiveTransaction(); + this.isInTxn = forceIsInTxn || isActiveTransaction(); // SQL usage inside a larger transaction (e.g. droptable) may not be desirable because // some databases (e.g. Postgres) abort the entire transaction when any query fails, so @@ -2394,6 +2405,10 @@ private void handleDirectSqlError(Exception ex) throws MetaException, NoSuchObje } throw new MetaException(ex.getMessage()); } + // If we are in a nested transaction, rollback can be destructive to the entire transaction, + // so we don't want to rollback and re-open in that case, and we want to try continuing with + // the same transaction. If we're the outermost transaction, though, it's better to re-initialize + // to give the jdo fallback the highest chance of success, if the issue is with the txn state. if (!isInTxn) { rollbackTransaction(); start = doTrace ? System.nanoTime() : 0; @@ -2454,8 +2469,8 @@ protected String describeResult() { * @throws MetaException */ public GetDbHelper( - String dbName, String tblName, boolean allowSql, boolean allowJdo) throws MetaException { - super(dbName,null,allowSql,allowJdo); + String dbName, String tblName, boolean allowSql, boolean allowJdo, boolean forceIsInTxn) throws MetaException { + super(dbName,null,allowSql,allowJdo,forceIsInTxn); } @Override