Am I missing it, or do you reset the deadlock count to 0 every time the
lock method is taken, so the ten count is never reached in checkRetryable()?
public LockResponse lock(LockRequest rqst)
throws NoSuchTxnException, TxnAbortedException, MetaException
{
>>> this.deadlockCnt = 0; <<<
try
{
Connection dbConn = null;
try
{
dbConn = getDbConn(8);
return lock(dbConn, rqst, true);
}
catch (SQLException e)
{
LOG.debug("Going to rollback");
rollbackDBConn(dbConn);
checkRetryable(dbConn, e, "lock(" + rqst + ")");
throw new MetaException("Unable to update transaction database " +
StringUtils.stringifyException(e));
}
finally
{
closeDbConn(dbConn);
}
return lock(rqst);
}
catch (RetryException e) {}
}
On Tue, Sep 22, 2015 at 9:24 PM, Steve Howard <[email protected]>
wrote:
> Hi Eugene,
>
> This is HDP 2.3, 1.2.1.2.3.0.0-2557.
>
> I see the deadlock count is 10, and we haven't overriden
> ConfVars.HMSHANDLERATTEMPTS, which also defaults to 10. I am at a loss why
> the call stack would be that large (I think it is 1,000), as that indicates
> to me it keeps failing to get the lock and keeps calling itself.
>
> protected void checkRetryable(Connection conn, SQLException e, String
> caller)
> throws TxnHandler.RetryException, MetaException
> {
> if ((this.dbProduct == null) && (conn != null)) {
> determineDatabaseProduct(conn);
> }
> if (((e instanceof SQLTransactionRollbackException)) ||
> (((this.dbProduct != DatabaseProduct.MYSQL) && (this.dbProduct !=
> DatabaseProduct.POSTGRES) && (this.dbProduct != DatabaseProduct.SQLSERVER))
> || ((e.getSQLState().equals("40001")) || ((this.dbProduct ==
> DatabaseProduct.POSTGRES) && (e.getSQLState().equals("40P01"))) ||
> ((this.dbProduct == DatabaseProduct.ORACLE) &&
> ((e.getMessage().contains("deadlock detected")) ||
> (e.getMessage().contains("can't serialize access for this
> transaction")))))))
> {
> if (this.deadlockCnt++ < 10)
> {
> long waitInterval = this.deadlockRetryInterval * this.deadlockCnt;
> LOG.warn("Deadlock detected in " + caller + ". Will wait " +
> waitInterval + "ms try again up to " + (10 - this.deadlockCnt + 1) + "
> times.");
> try
> {
> Thread.sleep(waitInterval);
> }
> catch (InterruptedException ie) {}
> throw new RetryException();
> }
> LOG.error("Too many repeated deadlocks in " + caller + ", giving
> up.");
> this.deadlockCnt = 0;
> }
> else if (isRetryable(e))
> {
> if (this.retryNum++ < this.retryLimit)
> {
> LOG.warn("Retryable error detected in " + caller + ". Will wait "
> + this.retryInterval + "ms and retry up to " + (this.retryLimit -
> this.retryNum + 1) + " times. Error: " + getMessage(e));
> try
> {
> Thread.sleep(this.retryInterval);
> }
> catch (InterruptedException ex) {}
> throw new RetryException();
> }
> LOG.error("Fatal error. Retry limit (" + this.retryLimit + ")
> reached. Last error: " + getMessage(e));
> this.retryNum = 0;
> }
> else
> {
> this.deadlockCnt = 0;
> this.retryNum = 0;
> }
> }
>
> Thanks,
>
> Steve
>
> On Tue, Sep 22, 2015 at 6:22 PM, Eugene Koifman <[email protected]>
> wrote:
>
>> What version of Hive are you running? In the current codebase at least,
>> TxnHandler.checkRetryable() keeps track of how many retries it allowed – it
>> will not retry forever.
>>
>>
>> From: Steve Howard <[email protected]>
>> Reply-To: "[email protected]" <[email protected]>
>> Date: Tuesday, September 22, 2015 at 1:32 PM
>> To: "[email protected]" <[email protected]>
>> Subject: Transaction deadlocks
>>
>>
>>
>> Thread A…
>>
>>
>>
>>
>>
>> "HiveServer2-Background-Pool: Thread-35" #35 prio=5 os_prio=0
>> tid=0x00007fd150e40000 nid=0x2c97 runnable [0x00007fd146e0a000]
>>
>> java.lang.Thread.State: RUNNABLE
>>
>> at java.net.SocketInputStream.socketRead0(Native Method)
>>
>> at
>> java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
>>
>> at java.net.SocketInputStream.read(SocketInputStream.java:170)
>>
>> at java.net.SocketInputStream.read(SocketInputStream.java:141)
>>
>> at oracle.net.ns.Packet.receive(Packet.java:300)
>>
>> at oracle.net.ns.DataPacket.receive(DataPacket.java:106)
>>
>> at
>> oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:315)
>>
>> at oracle.net.ns.NetInputStream.read(NetInputStream.java:260)
>>
>> at oracle.net.ns.NetInputStream.read(NetInputStream.java:185)
>>
>> at oracle.net.ns.NetInputStream.read(NetInputStream.java:102)
>>
>> at
>> oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:124)
>>
>> at
>> oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:80)
>>
>> at
>> oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1137)
>>
>> at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:290)
>>
>> at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
>>
>> at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
>>
>> at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:193)
>>
>> at
>> oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:1033)
>>
>> at
>> oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1329)
>>
>> at
>> oracle.jdbc.driver.OracleStatement.executeUpdateInternal(OracleStatement.java:1838)
>>
>> at
>> oracle.jdbc.driver.OracleStatement.executeUpdate(OracleStatement.java:1803)
>>
>> - locked <0x00000000c09fcda0> (a oracle.jdbc.driver.T4CConnection)
>>
>> at
>> oracle.jdbc.driver.OracleStatementWrapper.executeUpdate(OracleStatementWrapper.java:294)
>>
>> at
>> org.apache.commons.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)
>>
>> at
>> org.apache.commons.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:1432)
>>
>> - locked <0x00000000c09fcc28> (a java.lang.Object)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:422)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>>
>>
>>
>>
>> …blocks Thread B, resulting in a deadlock message being written to the
>> logs over and over again…
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> "HiveServer2-Background-Pool: Thread-51" #51 prio=5 os_prio=0
>> tid=0x000000000279f000 nid=0x7227 waiting for monitor entry
>> [0x00007fd146a47000]
>>
>> java.lang.Thread.State: BLOCKED (on object monitor)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:1361)
>>
>> - waiting to lock <0x00000000c09fcc28> (a java.lang.Object)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:422)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>> at
>> org.apache.hadoop.hive.metastore.txn.TxnHandler.lock(TxnHandler.java:433)
>>
>>
>>
>>
>>
>> …but my guess is the bigger issue is that eventually the stack will be
>> exhausted, as the method below recursively calls itself (notice the stack
>> above)…
>>
>>
>>
>>
>>
>> public LockResponse lock(LockRequest rqst)
>>
>> throws NoSuchTxnException, TxnAbortedException, MetaException
>>
>> {
>>
>> this.deadlockCnt = 0;
>>
>> try
>>
>> {
>>
>> Connection dbConn = null;
>>
>> try
>>
>> {
>>
>> dbConn = getDbConn(8);
>>
>> return lock(dbConn, rqst, true);
>>
>> }
>>
>> catch (SQLException e)
>>
>> {
>>
>> LOG.debug("Going to rollback");
>>
>> rollbackDBConn(dbConn);
>>
>> checkRetryable(dbConn, e, "lock(" + rqst + ")");
>>
>> throw new MetaException("Unable to update transaction database "
>> + StringUtils.stringifyException(e));
>>
>> }
>>
>> finally
>>
>> {
>>
>> closeDbConn(dbConn);
>>
>> }
>>
>> return lock(rqst);
>>
>> }
>>
>> catch (RetryException e) {}
>>
>> }
>>
>>
>>
>> This effectively freezes all access to a table.
>>
>> Any ideas?
>>
>
>