Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLite compatible with OpenAFS locking?

I would like to have many processes on many networked computers simultaneously access the same SQLite database via OpenAFS 1.4.12.1. Writes will be infrequent, so the single-write design of SQLite should not be a problem.

I would like to know if this is feasible. I am having trouble locating two crucial pieces of information:

The SQLite documentation states that "SQLite uses POSIX advisory locks to implement locking on Unix". It also warns that "Your best defense is to not use SQLite for files on a network filesystem". However, it does not seem to specify whether SQLite uses only whole-file locking, or whether it also uses byte-range locking.

I am also having trouble finding out which types of locking OpenAFS 1.4.12.1 supports. This unofficial source from 1998 is unfortunately the best source I have been able to find. Back then, whole-file locking was supported but byte-range locking was not.

The official documentation turns up only this page, which despite it's friendly title actually says nothing about whether POSIX byte-range advisory locking is supported by the latest OpenAFS.

EDIT: Is this possible at all? If so, are any compile-time SQLite flags needed?

like image 900
AlcubierreDrive Avatar asked Mar 29 '11 05:03

AlcubierreDrive


1 Answers

I have been using SQLite for quite some time and have had the "fortune" of dealing with some locking issues. I am pretty certain that SQLite uses byte-range locks on Unix filesystems by default.

To be more precise, it contains code for a few alternative locking methods (e.g using flock() and dotlock-style whole-file locks). When compiled with the SQLITE_ENABLE_LOCKING_STYLE option it attempts to auto-detect the proper locking method for the underlying filesystem.

The auto-detection code contains some hard-coded cases (e.g. "ufs", "nfs" and "smbfs"), none of which is AFS. If no hard-coded case matches, SQLite attempts to acquire a byte-range lock on a file using fcntl(). It then assumes that if the fcntl() call succeeds, then byte-range locks are available.

Here is where OpenAFS comes in to make things interesting. Apparently ([1], [2], [3]) OpenAFS has a long history of lying to the userspace applications about byte-range locks. From the openafs-1.4.14 source code:

/* next line makes byte range locks always succeed,
 * even when they should block */
if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
    DoLockWarning();
    afs_PutFakeStat(&fakestate);
    return 0;
}

In one word: Ouch!

It allows byte-range locks to succeed no matter what. On Linux, it is conceivably even worse: it uses the kernel infrastructure to provide byte-range locks among the processes of the same system. That means that an application cannot just fork a new process and test the locking mechanism - byte-range locks will appear to be working fine, while failing horribly to protect a file from remote processes.

In short: you cannot use an unmodified SQLite reliably with OpenAFS. Most other network filesystems have issues as well, hence the recommendation to avoid network filesystems completely.

A few possible work-arounds in no particular order:

  • Use a proper DBMS, such as PostgreSQL. If it is possible to do this, you'll be better off in the long run.

  • Implement your own server for your application, if a full-blown DBMS is overkill.

  • Modify the SQLite source code to default to flock() on OpenAFS. I am not sure if this will work properly, since OpenAFS has a long history ([1], [2]) of locking issues even with plain-old flock(), but you won't know until you test it.

  • Implement your own OpenAFS VFS for SQLite, using the OpenAFS userspace, rather than going through the kernel.

  • Try your luck with another network filesystem.

Whatever you do, you will have to perform extensive testing if in any way it involves SQLite3 and a shared database file.

EDIT:

A commenter suggested using the dotlock file mechanism. I didn't delve into the OpenAFS source code too much, but at first glance it appears to support the open(O_CREAT|O_EXCL) method of creating dotlock files that SQLite uses. If that works as it is supposed to, then SQLite might indeed be usable with OpenAFS if you force it to use the dotlock method.

That said, dotlocks are enough of a problem on regular local filesystems, without introducing the intricacies of a network filesystem into the mix - which is why I did not suggest it in the first place.

like image 101
thkala Avatar answered Sep 23 '22 06:09

thkala