简体   繁体   English

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

[英]How to resolve Lock wait timeout exceeded exception in SQL?

I am FTP'ing a file from a remote server and inserting/updating it in my db. 我正在通过FTP从远程服务器上传输文件,并将其插入/更新到我的数据库中。 I am using MySql db. 我正在使用MySql数据库。 But I am seeing java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction 但是我看到了java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction exception and also the row is being inserted into my db at the same time. java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction异常,并且该行同时插入到我的数据库中。 How can I resolve this issue?. 如何解决此问题?

The error from the log is below: 日志中的错误如下:

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)

The error points to rset = stmt.executeQuery (); 错误指向rset = stmt.executeQuery (); in the below code: 在下面的代码中:

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).");  
             }}
  }

The best thing would be control this using the auto increment of mysql. 最好的办法是使用mysql的自动增量来控制它。 But if you have to control the keys in your application, you can use this classes... 但是,如果您必须控制应用程序中的键,则可以使用此类。

SequenceBlockCache SequenceBlockCache

SequenceBlock 顺序块

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM