Khóa rượu - lý do?


262

Tôi nhận được điều này khi chạy rất nhiều tập lệnh hóa lỏng đối với máy chủ Oracle. Một số máy tính là tôi.

Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Liquibase Update Failed: Could not acquire change log lock.  Currently locked by SomeComputer (192.168.15.X) since 2013-03-20 13:39
SEVERE 2013-03-20 16:59:liquibase: Could not acquire change log lock.  Currently locked by SomeComputer (192.168.15.X) since 2013-03-20 13:39
liquibase.exception.LockException: Could not acquire change log lock.  Currently locked by SomeComputer (192.168.15.X) since 2013-03-20 13:39
        at liquibase.lockservice.LockService.waitForLock(LockService.java:81)
        at liquibase.Liquibase.tag(Liquibase.java:507)
        at liquibase.integration.commandline.Main.doMigration(Main.java:643)
        at liquibase.integration.commandline.Main.main(Main.java:116)

Có thể là số lượng phiên / giao dịch đồng thời đạt được? Bất cứ ai có ý tưởng?


2
Bạn đã giết JVM trong khi liquidibase giữ khóa? Đó là trường hợp duy nhất xảy ra với tôi.
Christoph Leiter

Dường như có một PC khác tham gia: Konsultpc74. Có lẽ bạn đã chạy liquidibase từ các PC khác nhau cùng một lúc? Nếu không bạn có một lời giải thích cho PC khác?
Jens

Tôi đã chỉnh sửa nhật ký và tôi vô tình quên thay đổi nó thành Một số máy tính
Peter Isberg

Bạn đang thực hiện các thay đổi đồng thời? Tôi nghĩ rằng mỗi tệp và mỗi thay đổi trong nó được thực hiện từng cái một. Ít nhất tôi sử dụng nó theo cách này. Tôi có một tập tin thay đổi chính bao gồm tất cả các tập tin khác và mọi thứ được chạy từng cái một.
Jens

Câu trả lời:


572

Đôi khi nếu ứng dụng cập nhật bị dừng đột ngột, khóa vẫn bị kẹt.

Sau đó chạy

UPDATE DATABASECHANGELOGLOCK SET LOCKED=0, LOCKGRANTED=null, LOCKEDBY=null where ID=1;

chống lại cơ sở dữ liệu giúp.

Hoặc bạn có thể chỉ cần thả DATABASECHANGELOGLOCKbảng, nó sẽ được tạo lại.


24
Tôi cần phải chuyển đổi 0cho FALSE, nhưng ngoài ra, nó hoạt động tốt. Cảm ơn
mattalxndr

7
Có một lệnh tích hợp trong Liquibase được gọi là releaseLocks sẽ thực thi những gì @Adrian Ber đã trả lời nhưng tôi nghĩ đó là bất khả tri về cơ sở dữ liệu.

1
Tôi chỉ nhận được lỗi này trong môi trường phát triển của tôi. Sửa lỗi bảng DATABASECHANGELOGLOCK đã giải quyết nó.
Naymesh Mology

1
Tôi cần chuyển đổi FALSEchob'0'
OrangePot

2
Đây là giải pháp chính xác, đừng thử làm trống bàn vì điều đó sẽ không giúp ích. Hoặc DROP nó hoặc CẬP NHẬT cờ LOCKED thành 'FALSE'
Aditya T

55

Chỉnh sửa tháng 6 năm 2020

Đừng làm theo lời khuyên này. Nó đã gây rắc rối cho nhiều người trong những năm qua. Nó đã làm việc cho tôi từ lâu và tôi đã đăng nó với thiện chí, nhưng rõ ràng đó không phải là cách để làm điều đó. Bảng DATABASECHANGELOCK cần phải có nội dung trong đó, vì vậy, chỉ nên xóa mọi thứ khỏi nó.

Ví dụ, Leos Literak đã làm theo các hướng dẫn này và máy chủ không khởi động được.

Câu trả lời gốc

Đó có thể là do một quá trình hóa lỏng bị giết không giải phóng khóa của nó trên bảng DATABASECHANGELOGLOCK. Sau đó,

DELETE FROM DATABASECHANGELOGLOCK;

có thể giúp bạn

Chỉnh sửa: Câu trả lời của @Adrian Ber cung cấp một giải pháp tốt hơn thế này. Chỉ làm điều này nếu bạn có bất kỳ vấn đề làm giải pháp của mình.


1
Điều này không cung cấp một câu trả lời cho câu hỏi. Để phê bình hoặc yêu cầu làm rõ từ một tác giả, hãy để lại nhận xét bên dưới bài đăng của họ.
Rachcha

@Rachcha Tôi giải thích rõ hơn. Hy vọng bạn thích nó nhiều hơn như thế này.
e18r

12
Đừng làm theo lời khuyên ở trên. DATABASECHANGELOGLOCK phải chứa các hàng mà không có bất kỳ hàng nào bạn sẽ có ngoại lệ
odedsh

Điều này không có ích, tôi đã thử điều này thay vì bỏ bảng hoặc cập nhật trạng thái bị khóa thành 'false'. Nó đã không làm việc.
Aditya T

Nếu bạn làm theo câu trả lời này, rất có thể các kịch bản trong tương lai sẽ không chạy vì họ hy vọng khóa sẽ tồn tại. Nếu bạn đã làm điều này rồi, bạn có thể thêm một khóa trống để khắc phục sự cố INSERT INTO yourdb.DATABASECHANGELOGLOCK VALUES (1, 0, null, null);
Rudi Kershaw

24

Vấn đề là lỗi triển khai SequenceExists trong Liquibase. Vì những thay đổi với những tuyên bố này mất một thời gian rất dài và đã vô tình bị hủy bỏ. Sau đó, lần thử tiếp theo thực hiện các kịch bản hóa lỏng, khóa được giữ.

  <changeSet author="user" id="123">
    <preConditions onFail="CONTINUE">
      <not><sequenceExists sequenceName="SEQUENCE_NAME_SEQ" /></not>
    </preConditions>
    <createSequence sequenceName="SEQUENCE_NAME_SEQ"/>
  </changeSet>

Một công việc xung quanh là sử dụng SQL đơn giản để kiểm tra điều này thay vào đó:

  <changeSet author="user" id="123">
    <preConditions onFail="CONTINUE">
            <sqlCheck expectedResult="0">
              select count(*) from user_sequences where sequence_name = 'SEQUENCE_NAME_SEQ';
            </sqlCheck>
    </preConditions>
    <createSequence sequenceName="SEQUENCE_NAME_SEQ"/>
  </changeSet>

Lockdata được lưu trữ trong bảng DATABASECHANGELOCK. Để thoát khỏi khóa, bạn chỉ cần thay đổi 1 thành 0 hoặc thả bảng đó và tạo lại.


1
Trong liquidibase 3.0.2 (phiên bản tôi đang sử dụng), không xóa một dòng khỏi bảng khóa, hoặc bạn sẽ gặp lỗi khác khi chạy liquidibase vào lần tiếp theo, bởi vì Liquidibase hy vọng rằng một hàng sẽ ở đó (hoặc thiếu toàn bộ bàn). Chính xác như Peter đã nói, chỉ muốn thêm thông tin đó, bởi vì trong các phiên bản cũ hơn, nó dường như đã hoạt động để loại bỏ hàng.
Kariem

7

Nó không được đề cập đến môi trường nào được sử dụng để thực hiện Liquibase. Trong trường hợp đó là Spring Boot 2, có thể mở rộng liquibase.lockservice.StandardLockServicemà không cần chạy các câu lệnh SQL trực tiếp sạch hơn nhiều. Ví dụ:

/**
 * This class is enforcing to release the lock from the database.
 *
 */
 public class ForceReleaseLockService extends StandardLockService {

    @Override
    public int getPriority() {
        return super.getPriority()+1;
    }

    @Override
    public void waitForLock() throws LockException {
        try {
            super.forceReleaseLock();
        } catch (DatabaseException e) {
            throw new LockException("Could not enforce getting the lock.", e);
        }
        super.waitForLock();
    }
}

Mã này đang thực thi việc phát hành khóa. Điều này có thể hữu ích trong các thiết lập thử nghiệm trong đó lệnh gọi phát hành có thể không được gọi trong trường hợp có lỗi hoặc khi gỡ lỗi bị hủy bỏ.

Lớp phải được đặt trong liquibase.extgói và sẽ được chọn bởi cấu hình tự động Spring Boot 2.


Bạn có thể vui lòng cung cấp một mô tả chi tiết hơn về giải pháp của bạn? Chúng tôi sử dụng Spring Boot 2 và liquidibase và không muốn xóa trạng thái khóa trong db mỗi lần theo cách thủ công. Nhưng tôi không hiểu làm thế nào để bạn tiêm ForceReleaseLockService vào liquidibase. Tôi không phải đặt chú thích Dịch vụ / Thành phần cho lớp này, Spring có chọn nó làm bean chính không?
Andrej Tihonov

1
Nó được đề cập trong câu cuối cùng: "Lớp phải được đặt trong gói liquidibase.ext và sẽ được chọn bởi cấu hình tự động Spring Boot 2".
k_o_

Làm thế nào để bạn đặt lớp vào liquibase.ext, tôi có cần xác định gói đó trong dự án của tôi không?
akuma8

Tôi đã xác định gói đó trong dự án của tôi, nó có vẻ hoạt động nhưng tôi không thể xác minh nó. Tôi đã định nghĩa một @PostConstructphương thức với một thông điệp tường trình nhưng tôi không thấy nó được in.
akuma8

@ akuma8: Có, chỉ cần tạo một gói trong dự án của bạn với tên đó. Bạn đã xác định @PostConstructphương pháp ở đâu? Trong ForceReleaseLockService? Đây không phải là một dịch vụ mùa xuân, vì vậy điều này sẽ không được gọi.
k_o_

3

Đôi khi, việc cắt hoặc bỏ bảng DATABASECHANGELOGLOCK không hoạt động. Tôi sử dụng cơ sở dữ liệu PostgreSQL và đã gặp vấn đề này rất nhiều lần. Những gì tôi làm để giải quyết là khôi phục các câu lệnh đã chuẩn bị đang chạy trong nền cho cơ sở dữ liệu đó. Cố gắng khôi phục lại tất cả các báo cáo đã chuẩn bị và thử lại các thay đổi về chất lỏng.

SQL:

SELECT gid FROM pg_prepared_xacts WHERE database='database_name';

Nếu câu lệnh trên trả về bất kỳ bản ghi nào, thì rollback câu lệnh đã chuẩn bị với câu lệnh SQL sau.

ROLLBACK PREPARED 'gid_obtained_from_above_SQL';

1

Bạn có thể xóa bảng một cách an toàn hoặc sử dụng truy vấn. Nó sẽ được tạo lại tự động.

DROP TABLE DATABASECHANGELOGLOCK;

0

Tôi đánh giá cao đây không phải là vấn đề của OP, nhưng tôi đã gặp vấn đề này gần đây với một nguyên nhân khác. Để tham khảo, tôi đã sử dụng plugin Liquibase Maven (liquidibase-maven-plugin: 3.1.1) với SQL Server.

Dù sao, tôi đã sao chép và dán nhầm câu lệnh "sử dụng" SQL Server vào một trong các tập lệnh của tôi để chuyển đổi cơ sở dữ liệu, do đó, Liquidibase đang chạy và cập nhật DATABASECHANGELOGLOCK, lấy khóa trong cơ sở dữ liệu chính xác, nhưng sau đó chuyển cơ sở dữ liệu để áp dụng các thay đổi. Tôi không chỉ KHÔNG thể thấy các thay đổi hoặc kiểm toán hóa lỏng trong cơ sở dữ liệu chính xác, mà tất nhiên, khi tôi chạy lại hóa đơn, nó không thể có được khóa, vì khóa đã được phát hành trong cơ sở dữ liệu "sai", và vì vậy vẫn bị khóa trong cơ sở dữ liệu "chính xác". Tôi đã mong đợi chất lỏng để kiểm tra khóa vẫn được áp dụng trước khi phát hành và có thể đó là một lỗi trong chất lỏng (tôi chưa kiểm tra), nhưng nó có thể được xử lý trong các phiên bản sau! Điều đó nói rằng, tôi cho rằng nó có thể được coi là một tính năng!

Tôi biết một chút lỗi của một cậu học sinh, nhưng tôi nêu ra ở đây trong trường hợp có ai gặp phải vấn đề tương tự!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.