DB Processes

On the lowest level, the db consists of independent objects ("external symbols"). When a process accesses such a symbol, it obtains a read-lock on the db, reads it, and releases the lock. In the following, it operates on its objects in memory (i.e. the objects are cached), and a 'commit' will write all modified objects to the db (after obtaining a write-lock).

Thus, any number of processes may read the db, but only a single one will be able to write at a time (while all reads are blocked during that time).

This works for independent processes, too, but only guarantees the consistency of individual objects (that is, no two processes can write at the same time, and an object read by one process cannot be changed by another process while the reading takes place).

It does, however, not synchronize the state of objects cached on different processes, and may in particular result in inconsistencies, if a transaction changes a set of interdependent objects, and other processes have some of these objects cached and some not.

Before a process begins to change a set of objects for a transaction, it is supposed to call (dbSync). This will request a write-lock, and until that request is granted, all modifications done on the db by other processes will be relayed to the waiting process. This happens via pipes between the parent and the child processes. When the process is done modifying the objects, it should call (commit 'upd) so write the data to the db (or (rollback) to undo the changes) and to release the lock.

If you have an independent process (outside the common parent process) accessing such a db, it must make sure never to write to that db (or write only objects which are guaranteed not to be written by other processes), and be aware that the state of its cached objects might be out of date (e.g. call (rollback) from time to time to cause a reload).

This is usually not so easy to guarantee, because changing a single object often triggers the change of many other objects as a side effect, like objects connected via '+Joint', or whole branches of an index tree.

Locking and Transactions

For the mechanism described above, the lock will always be for the whole database. It is possible to lock individual objects, too, this is done for example in "lib/form.l" to give to a user exclusive access rights for an object.

To be on the safe side, I would recommend to allow only members of a single family to access a db, and implement external accesses via some RPC mechanisms (for queries, '*Ext' comes in handy here). Only when absolutely sure, begin to bypass these mechanisms.


19mar16   erik