1. 程式人生 > 實用技巧 >Mysql lock wait timeout

Mysql lock wait timeout





前段時間遇到一個問題,有個事務內的程式碼,但是顯然沒有全部回滾,導致業務事務不完整;error message如下
org.springframework.dao.CannotAcquireLockException: 
### Error updating database.  Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

   如上顯示,遇到的MySQLTransactionRollbackException,觸發原因是“鎖等待超時”,從mysql connector中丟擲,丟擲位置的程式碼如下,可以看到

#SQLError.class
public static SQLException createSQLException(String message, String sqlState, int vendorErrorCode, boolean isTransient, Throwable cause,
            ExceptionInterceptor interceptor) {
        try {
            SQLException sqlEx = null;

            if (sqlState != null) {
                if (sqlState.startsWith("08")) {
                    if (isTransient) {
                        sqlEx = new SQLTransientConnectionException(message, sqlState, vendorErrorCode);
                    } else {
                        sqlEx = new SQLNonTransientConnectionException(message, sqlState, vendorErrorCode);
                    }

                } else if (sqlState.startsWith("22")) {
                    sqlEx = new SQLDataException(message, sqlState, vendorErrorCode);

                } else if (sqlState.startsWith("23")) {
                    sqlEx = new SQLIntegrityConstraintViolationException(message, sqlState, vendorErrorCode);

                } else if (sqlState.startsWith("42")) {
                    sqlEx = new SQLSyntaxErrorException(message, sqlState, vendorErrorCode);
                  //40開頭的sqlstate都會丟擲這個異常
                } else if (sqlState.startsWith("40")) {
                    sqlEx = new MySQLTransactionRollbackException(message, sqlState, vendorErrorCode);

                } else if (sqlState.startsWith("70100")) {
                    sqlEx = new MySQLQueryInterruptedException(message, sqlState, vendorErrorCode);

                } else {
                    sqlEx = new SQLException(message, sqlState, vendorErrorCode);
                }
            } else {
                sqlEx = new SQLException(message, sqlState, vendorErrorCode);
            }

            if (cause != null) {
                try {
                    sqlEx.initCause(cause);
                } catch (Throwable t) {
                    // we're not going to muck with that here, since it's an error condition anyway!
                }
            }

            return runThroughExceptionInterceptor(interceptor, sqlEx);

        } catch (Exception sqlEx) {
            SQLException unexpectedEx = new SQLException(
                    "Unable to create correct SQLException class instance, error class/codes may be incorrect. Reason: " + Util.stackTraceToString(sqlEx),
                    MysqlErrorNumbers.SQL_STATE_GENERAL_ERROR);

            return runThroughExceptionInterceptor(interceptor, unexpectedEx);

        }
    }

    在mysql connector文件中有如下表格





    到這裡有幾個疑問,1.什麼情況下會造成lock wait timeout?2.為什麼lock timeout為什麼事務不全部回滾?3.為什麼這裡的異常命名用MySQLTransactionRollbackException?

1.什麼情況下會造成lock wait timeout?

mysql官網可以看得到關於lock wait timeout相關的配置如下,由於一行資料被另一個事務鎖定,導致當下的事務一直等待,直至超時!




2.為什麼lock timeout為什麼事務不全部回滾?

繼續往下看,可以知道mysql服務隊鎖等待超時的情況,並不會整個回滾該資料