Linux process cannot write to sqlite database
(1) By Gulsah (12870610) on 2023-03-16 10:25:40 [link] [source]
Hi,
I am getting write error while trying to manipulate a Sqlite DB. Here is the configuration;
SqliteDb file is placed on a Windows Server 2012 Machine, via shared folder. But this folder is shared only one specific user (not everyone) and SMB2 protocol is used for encrypted network traffic.
My process manipulating the db is running on Centos 7.9. To reach the folder on Windows share, I am creating a mounting point with the following command;
mount -t cifs -o username=specificUser,password=xxx,domain=Domain, //WindowsMachineIP/SqliteDBFolder /home/mySqliteDBFolder rw
My process is searching for a db file on mySqliteDBFolder, finds it and writes some data. Everything is okay until write operation.
not: I also try to manuplate a txt file, all read write operations can be done, there is a problem with Sqlite.
I will be glad for any suggestion.
Thanks in advance.
(2) By Stephan Beal (stephan) on 2023-03-16 12:29:36 in reply to 1 [link] [source]
mount -t cifs -o username=specificUser,password=xxx,domain=Domain, //WindowsMachineIP/SqliteDBFolder /home/mySqliteDBFolder rw
According to the man page, that should not work: the final argument to mount
is the mount point. "rw" should in the comma-separated -o list.
not: I also try to manuplate a txt file, all read write operations can be done, there is a problem with Sqlite.
Make sure that not only the db file, but also the directory containing the db file is writable on both the Windows server and the mount point which is masking that remote folder. That's necessary for sqlite to create temp files. This part can be simulated by creating any new file in that dir from the Linux side using the same account which runs your application:
$ cd /home/mySqliteDBFolder
$ cp /etc/hosts .
If it doesn't work, that's possibly where the problem is. If that works, the directory itself is writable, in which case the only suggestion i can make is to disable any virus scanner on the Windows machine, or at least filter the db's directory out of the virus scanner.
(3.1) By Keith Medcalf (kmedcalf) on 2023-03-16 13:00:58 edited from 3.0 in reply to 1 [link] [source]
You also need read/write access to the local tempstore.
However, SQLite3 cannot work on filesystems which do not implement proper locking behaviour. This is common on "interposer" or "proxy" filesystems such as network filesystems or docker or the like, that "interpose" or "proxy" access to the underlying "real" filesystem via a "proxy", "RPC", or other "interposer" layer and in the process of doing so fail to implement proper advisory locking.
Perhaps I am blind, but I did not see you posting an error message, simply claiming "no worky". What is the error message/code? Better yet, what is the extended error code?
Try using the unix-dotfile VFS to open the file and see if that makes a difference.
(4.1) By Gulsah (12870610) on 2023-03-16 13:22:31 edited from 4.0 in reply to 3.1 [link] [source]
Thanks for the quick response, Sorry for missing error message, you can find the error below:
org.sqlite.SQLiteException: [SQLITE_BUSY] The database file is locked (database is locked) at org.sqlite.core.DB.newSQLException(DB.java:1018) at org.sqlite.core.DB.newSQLException(DB.java:1031) at org.sqlite.core.DB.execute(DB.java:870) at org.sqlite.core.DB.executeUpdate(DB.java:911) at org.sqlite.jdbc3.JDBC3PreparedStatement.executeUpdate(JDBC3PreparedStatement.java:98) at
(5) By Gulsah (12870610) on 2023-03-16 13:11:50 in reply to 2 [link] [source]
Thanks for the response,
I am sure about that: the directory containing the db file is writable on both the Windows server and the mount point which is masking that remote folder.
I can create/modify/delete files on the folder containing db file.
(6) By Rowan Worth (sqweek) on 2023-03-17 03:19:44 in reply to 4.1 [link] [source]
For SMB I've found it important to disable opportunistic locking on the server to allow multiple clients to use the same database simultaneously, however it's not clear this explains your issue if you really only have a single client.
(7) By Vadim Goncharov (nuclight) on 2023-03-29 07:18:52 in reply to 3.1 [link] [source]
Hmm, dicker too? Probably it should be put into SQLite documentation on "how to corrupt" page ("don't put on share/docker"), then?
(8) By Stephan Beal (stephan) on 2023-03-29 07:26:31 in reply to 7 [link] [source]
Hmm, docker too? Probably it should be put into SQLite documentation on "how to corrupt" page ("don't put on share/docker"), then?
Section 2 of that page covers locking-related issues extensively. The developers of this project cannot feasibly maintain a list of all environments which are anecdotally believed to have sub-par locking support and the devs certainly cannot personally test all such platforms, so it would be irresponsible to list specific platforms/products there. Anecdotally, docker, or some versions or setups of it, might fall into section 2.1's warning. However, at least one of our frequent forum-goers has done extensive sqlite corruption testing on docker and, to the best of my knowledge, been unable to reproduce any corruption.
(9) By AlexJ (CompuRoot) on 2023-03-29 12:06:04 in reply to 1 [source]
It pretty tricky workflow, Locking on windows is always based on unknown magic. I suggest to talk to sqlite
in such environment over network instead of over share. Take any wrapper like gosqlapi and use curl
(on Unixes or powershell
on windows) to "talk" to remote sqlite
database.
(10) By Warren Young (wyoung) on 2023-03-29 14:05:46 in reply to 3.1 [link] [source]
docker…that "interpose" or "proxy" access to the underlying "real" filesystem
Docker doesn't do any of that. When you make a Linux syscall manipulating a file inside a Linux container — whether managed by Docker or any of the other OCI container implementations — it goes up to the actual host kernel and is processed much like the call from a program running on the host. The only thing that's interposed are normal Linux mechanisms that you can use (or not) from the host side as well:
- Good old Unix permission checking
- Your distro's chosen MAC system; most likely, SELinux or AppArmor
capabilities(7)
pare root's power down, if you're running any of these processes as rootcgroups(7)
liimit how much CPU, memory, network, etc a given container can usenamespaces(7)
keep individual containers from seeing what is going on in other containersseccomp(2)
blocks access to problematic system calls
That's the essentials of containers, right there. It's why we now have so many implementations of OCI. What Docker did was only clever inasmuch as they brought all these pieces together and made it easy to configure them for useful purposes. They added nothing new to the Linux kernel, merely made solid, well-reasoned use of what they found there, preexisting.
When a process inside a Linux container writes to a file, and the write passes all those checks, it goes straight through the kernel, through its VFS layer to the filesystem driver, and down to the storage media. There is no other "imposition" or "proxying."
Namespaces can make it so one container can't even see another container's files, but it can't give you a half-broken view of them, allowing writes but breaking locking, as you seem to be imputing.
The only way to do that would be to misconfigure seccomp atop that, denying the container access to flock(2)
and similar. The default Docker seccomp profile doesn't do that. You can see for yourself that the necessaries like fcntl(2)
and flock()
are allowed by this profile. While one could write a new profile and apply it to a given container, that's rare to see, and it would be the user's lookout anyway, not subject to generalized slagging-on by people ignorant of the relevant technologies. (Ahem.)
I'm not going to tell you that Docker cannot possibly result in SQLite corruption, but out of the box, my documented testing experience is that it doesn't.
(11) By Warren Young (wyoung) on 2023-03-29 14:10:51 in reply to 9 [link] [source]
Add Bedrock to your list of options. Any of these HTTP layers should make SQLite safe to use over the network by putting all of the locking in one central process, running on the server.
This is approximately what Fossil's sync protocol does, by the way, and for much the same reason: it allows two SQLite DBs (called the "repository" in Fossil-speak) to send messages about what each DB should change in itself, using local file locking only.
This is the way.