如何确定是否存在H2数据库文件锁?

时间:2021-06-02 02:24:00

For reasons that I will not explain (because people will direct their responses at the other topic, instead of my problem at hand), I need to know how to determine whether or not my H2 database is locked. Using Java code, how do I determine whether or not the lock file exists on my database?

由于我不会解释的原因(因为人们会在另一个主题上指导他们的回答,而不是我手头的问题),我需要知道如何确定我的H2数据库是否被锁定。使用Java代码,如何确定数据库中是否存在锁定文件?

1 个解决方案

#1


5  

For others reading this question I need to explain why you you shouldn't do it yourself, and let the database detect itself whether it is locked or not. First of all, database file locking is an implementation detail that can and will change in future versions of the database. Then, there is a race condition: if you see the lock doesn't exist now, it may exist one second later. So the only reliable way is to try locking. So: try opening the database in read-write mode. Disadvantage: it is a bit slow, as it will initialize the database and also run the recovery code if needed. I understand this is not what you want, because it is slow (right?).

对于读这个问题的其他人,我需要解释为什么你不应该自己做,并让数据库自己检测它是否被锁定。首先,数据库文件锁定是一种实现细节,可以在将来的数据库版本中进行更改。然后,存在竞争条件:如果您现在看到锁不存在,则可能在一秒之后存在。因此唯一可靠的方法是尝试锁定。所以:尝试以读写模式打开数据库。缺点:它有点慢,因为它将初始化数据库并在需要时运行恢复代码。我明白这不是你想要的,因为它很慢(对吧?)。

For lower level method, it depends which version of H2 you use.

对于较低级别的方法,它取决于您使用的H2版本。

Version 1.4 (currently beta)

Try locking the file itself using the following code:

尝试使用以下代码锁定文件本身:

static boolean isLocked(String fileName) {
    try {
        RandomAccessFile f = new RandomAccessFile(fileName, "r");
        try {
            FileLock lock = f.getChannel().tryLock(0, Long.MAX_VALUE, true);
            if (lock != null) {
                lock.release();
                return false;
            }
        } finally {
            f.close();
        }
    } catch (IOException e) {
        // ignore
    }
    return true;
}

Or using H2 code (from the MVStore):

或使用H2代码(来自MVStore):

static boolean isLocked(String fileName) {
    FileStore fs = new FileStore();
    try {
        fs.open(fileName, true, null);
        return false;
    } catch (IllegalStateException e) {
        return true;
    } finally {
        fs.close();
    }
}

Version 1.3 (stable) and 1.4 with the MVStore disabled

Simply checking if the file <databaseName>.lock.db exists is not enough. It might exist even the database is not open, in case the process was killed. So some sample code (not tested) is:

只需检查文件 .lock.db是否存在是不够的。如果进程被终止,即使数据库未打开也可能存在。所以一些示例代码(未经测试)是:

// file name must be:
// path + databaseName + Constants.SUFFIX_LOCK_FILE
static boolean isLocked(String fileName) {
    try {
        FileLock lock = new FileLock(new TraceSystem(null), fileName, 1000);
        lock.lock(FileLock.LOCK_FILE);
        lock.unlock();
        return false;
    } catch (Exception e) {
        return true;
    }
}

#1


5  

For others reading this question I need to explain why you you shouldn't do it yourself, and let the database detect itself whether it is locked or not. First of all, database file locking is an implementation detail that can and will change in future versions of the database. Then, there is a race condition: if you see the lock doesn't exist now, it may exist one second later. So the only reliable way is to try locking. So: try opening the database in read-write mode. Disadvantage: it is a bit slow, as it will initialize the database and also run the recovery code if needed. I understand this is not what you want, because it is slow (right?).

对于读这个问题的其他人,我需要解释为什么你不应该自己做,并让数据库自己检测它是否被锁定。首先,数据库文件锁定是一种实现细节,可以在将来的数据库版本中进行更改。然后,存在竞争条件:如果您现在看到锁不存在,则可能在一秒之后存在。因此唯一可靠的方法是尝试锁定。所以:尝试以读写模式打开数据库。缺点:它有点慢,因为它将初始化数据库并在需要时运行恢复代码。我明白这不是你想要的,因为它很慢(对吧?)。

For lower level method, it depends which version of H2 you use.

对于较低级别的方法,它取决于您使用的H2版本。

Version 1.4 (currently beta)

Try locking the file itself using the following code:

尝试使用以下代码锁定文件本身:

static boolean isLocked(String fileName) {
    try {
        RandomAccessFile f = new RandomAccessFile(fileName, "r");
        try {
            FileLock lock = f.getChannel().tryLock(0, Long.MAX_VALUE, true);
            if (lock != null) {
                lock.release();
                return false;
            }
        } finally {
            f.close();
        }
    } catch (IOException e) {
        // ignore
    }
    return true;
}

Or using H2 code (from the MVStore):

或使用H2代码(来自MVStore):

static boolean isLocked(String fileName) {
    FileStore fs = new FileStore();
    try {
        fs.open(fileName, true, null);
        return false;
    } catch (IllegalStateException e) {
        return true;
    } finally {
        fs.close();
    }
}

Version 1.3 (stable) and 1.4 with the MVStore disabled

Simply checking if the file <databaseName>.lock.db exists is not enough. It might exist even the database is not open, in case the process was killed. So some sample code (not tested) is:

只需检查文件 .lock.db是否存在是不够的。如果进程被终止,即使数据库未打开也可能存在。所以一些示例代码(未经测试)是:

// file name must be:
// path + databaseName + Constants.SUFFIX_LOCK_FILE
static boolean isLocked(String fileName) {
    try {
        FileLock lock = new FileLock(new TraceSystem(null), fileName, 1000);
        lock.lock(FileLock.LOCK_FILE);
        lock.unlock();
        return false;
    } catch (Exception e) {
        return true;
    }
}