如何解决SQL中的锁定等待超时超出异常?

时间:2014-08-27 23:00:40

标签: java mysql sql jdbc

我是来自远程服务器的FTP文件,并在我的数据库中插入/更新它。我正在使用MySql db。但我看到java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction异常,同时该行也被插入到我的数据库中。我该如何解决这个问题?。

日志中的错误如下:

SEVERE: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4187)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4119)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2815)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
    at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2322)
    at com.sun.gjc.spi.jdbc40.PreparedStatementWrapper40.executeQuery(PreparedStatementWrapper40.java:642)
    at ft.util.KeyGenerator.generateKey(KeyGenerator.java:92)
    at ft.util.KeyGenerator.generateKey(KeyGenerator.java:44)
    at processes.FTPInbound.connectAndGetListOfFiles(FTPInbound.java:242)
    at com.washpost.main.Main.main(Main.java:24)
    at lockbox.beans.LOCKBOX_MessageBean.onMessage(LOCKBOX_MessageBean.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

错误指向以下代码中的rset = stmt.executeQuery ();

package com.washpost.ft.util;

import java.io.*;
import java.util.*;
import java.sql.*;

import java.util.logging.*;


public class KeyGenerator {

  private static HashMap keyTbl = new HashMap();
  private static Vector  keyLock = new Vector();
  private final static   long  MAX_KEY_COUNT = 999999999;
  private final static   int   KEY_INC_COUNTER = 1;



  public KeyGenerator() {
  }

  public static long generateKey(String sequenceName)
                                throws Exception {
           long keyValue;

           synchronized(keyLock) {

                  String key =  sequenceName;

                  Key data = (Key) keyTbl.get(key);

                  if(data == null || (data.currentValue == data.maxValue)) {

                           // Need to put retry logic
                           keyValue =  generateKey(sequenceName,KEY_INC_COUNTER);

                           if(keyValue == -1) {
                               throw new Exception ("SequenceName not in SEQUENCE_GENERATOR table :" + sequenceName );
                           }

                           data = new Key(keyValue,keyValue,keyValue + KEY_INC_COUNTER);

                           keyTbl.put(key,data);
                  }
                  keyValue = data.currentValue;

                  data.currentValue++;

                  return keyValue;
           }
  }


  public static synchronized long generateKey(String sequenceName,int count)
                                throws Exception {

             PreparedStatement stmt=null;
             ResultSet rset=null;
             Connection db_conn = null;
             StringBuffer sql = new StringBuffer();
             long key=-1;
             long maxKeyCount;
             String sqlSeqNum="";

             try {

              //     db_conn = Utility.getConnection("PASDataSource");
                     db_conn = Util.getConnection("ftpds");

                   sql.append("SELECT SEQ_NUM ");
                   sql.append("FROM SEQUENCE_GENERATOR ");
                   //SJ 2009.02.11, commented and added line below
                   //sql.append("WHERE sequence_name = ? ");
                    sql.append("WHERE SEQUENCE_NAME = ? for update");

                   System.out.println(sql + "::" + sequenceName);
                   stmt = db_conn.prepareStatement(sql.toString());

                   stmt.clearParameters();

                   stmt.setString(1,sequenceName);

                   rset = stmt.executeQuery ();

                    // Iterate through the result set
                    while(rset.next()) {
                          key =   rset.getInt(1);

                          // Update the key
                    }
                    rset.close();
                    stmt.close();
                    stmt = null;
                    rset = null;

                    if(key != -1) {

                          if((key + count) > MAX_KEY_COUNT) {
                              // reset key count
                              // key = 1;
                              sqlSeqNum = "";
                          }
                          else
                              sqlSeqNum = " seq_num + ";

                          sql = new StringBuffer();
                          sql.append("UPDATE SEQUENCE_GENERATOR SET SEQ_NUM = " + sqlSeqNum  + count );
                          sql.append(" WHERE SEQUENCE_NAME = ? ");
                          sql.append(" AND   SEQ_NUM = ? ");
                          stmt = db_conn.prepareStatement(sql.toString());

                          stmt.clearParameters();

                          stmt.setString(1,sequenceName);
                          stmt.setLong(2,key);

                          if(stmt.executeUpdate() != 1) {
                               System.out.println(
                                           ":Not able to generate a new UNIQUE key for sequence :" + sequenceName);
                               throw new Exception("Not able to generate a new UNIQUE key for sequence :" + sequenceName );
                          }
                          return key;
                    }

                    return -1;
               }
               catch (Exception e) {
                     System.out.println(e.getMessage());
                     throw e;
               }
             finally { 
                 Util.release(db_conn, stmt, rset);
                 System.out.println("Closing Connection in KeyGenerator(generateKey).");  
             }}
  }

1 个答案:

答案 0 :(得分:2)

最好的方法是使用mysql的自动增量来控制它。 但是,如果您必须控制应用程序中的键,则可以使用此类...

SequenceBlockCache

SequenceBlock