Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Làm thế nào để xử lý đúng cách các deadlock InnoDB trong Java / JDBC?

Mã của bạn về cơ bản là chính xác. Ngoại lệ được đưa ra khi xảy ra khóa chết là SQLException . getSQLState() của ngoại lệ phương thức cung cấp trả về mã lỗi cung cấp thông tin bổ sung về lỗi thực tế.

Bạn cũng nên đợi một khoảng thời gian ngắn giữa các lần tham dự để không tải máy chủ của bạn quá nhiều.

Như bạn đã đoán khéo léo, hãy đặt số lần thử tối đa, nếu không bạn có thể kết thúc trong một vòng lặp vô hạn.

Mã cuối cùng có thể trông như thế này:

boolean oops;
int retries = 5;
Connection c = null;
Statement s = null;
ResultSet rs = null;    

do
{
    oops = false;
    c = null;
    s = null;
    rs = null;
    try
    {
        c = openConnection();
        s = c.createStatement();
        rs = s.executeQuery("SELECT stuff FROM mytable");
        fiddleWith(rs);
    }
    catch (SQLException sqlex)
    {
        oops = true;
        switch(sqlex.getErrorCode()())
        {
            case MysqlErrorNumbers.ER_LOCK_DEADLOCK:
                // deadlock or lock-wait time-out occured
                break;
            ...
        }
        Thread.sleep(1000); // short delay before retry
    }
    finally
    {
        if (rs != null) try {
            rs.close();
        } catch (SQLException e) {
            // some error handler here
        }

        if (s != null) try {
            s.close();
        } catch (SQLException e) {
            // some error handler here
        }

        if (c != null) try {
            c.close();
        } catch (SQLException e) {
            // some error handler here
        }

    }
}
while (oops == true && retries-- > 0);

Rõ ràng đoạn mã trên là tối ưu phụ. Bạn có thể muốn phân biệt lỗi diễn ra tại thời điểm kết nối và lỗi tại thời điểm thực thi. Bạn cũng có thể phát hiện ra rằng sau một số lỗi, có rất ít hy vọng rằng nỗ lực khác sẽ hoạt động (ví dụ:thông tin đăng nhập sai hoặc lỗi cú pháp SQL).

Bạn đã hỏi rất nhiều câu hỏi, nhưng tôi sẽ cố gắng trả lời tất cả:

Có, hãy xem ở trên:SQLException là những cái đó, với nhiều thông tin hơn được cung cấp bởi getErrorCode() hoặc getSQLState() .

Một SQLException có thể được ném bởi hầu như tất cả các phương thức của tất cả các lớp từ java.sql gói hàng.

Có, xem ở trên.

Rõ ràng là bạn không được tạo lại PreparedStatement giữa hai truy vấn. Bạn chỉ cần đặt các giá trị mới cho các tham số của mình trước khi gọi executeQuery() lần nữa. Tất nhiên, nếu bạn cần thực hiện một truy vấn khác, thì một PreparedStatement mới là bắt buộc.

A (mới) ResultSet đối tượng được trả về bởi Statement.executeQuery() , đại diện cho kết quả của truy vấn. Bạn không bao giờ tự mình tạo ra một đối tượng như vậy. Lý tưởng nhất là bạn sẽ gọi ResultSet.close() càng sớm càng tốt để giải phóng bộ nhớ.

Tôi thực sự khuyên bạn nên làm theo chương thứ hai của hướng dẫn này ("Xử lý câu lệnh SQL").




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chọn hàng có ngày gần đây nhất cho mỗi người dùng

  2. Làm cách nào để bạn kết nối hiệu quả với mysql trong php mà không cần kết nối lại trên mọi truy vấn

  3. Sự khác biệt giữa LIKE và =trong MYSQL?

  4. Thủ tục lưu trữ đệ quy Mysql ... Đã đạt đến giới hạn 0 ... không thể thay đổi biến max_sp_recursion_depth

  5. Tìm kiếm nhiều số trong trường nhiều số