Traditionally, Prolog database updates add or remove individual clauses. The Logical Update View ensures that a goal that is started on a dynamic predicate does not see modifications due to assert/1 or retract/1 during its life time. See section 4.13.5. In a multi-threaded context this assumption still holds for individual predicates: concurrent modifications to a dynamic predicate are invisible.
Transactions allow running a goal in isolation. The goals running inside the transaction‘see' the database as it was when the transaction was started together with database changes done by the transaction goal. Other threads see no changes until the transaction is committed. The commit, also if it involved multiple clauses spread over multiple predicates, becomes atomically visible to other threads. Transactions have several benefits Wielemaker, 2013
- If a database update requires multiple assert/1
operations, a transaction ensure either all are executed or the database
remains unchanged. Notably unexpected exceptions or failures cannot
leave the database in an inconsistent state.
- Other threads do not see the intermediate inconsistent states when a
database update that consists of multiple assert and/or retract is
performed in a transaction. This notably avoids the need to use locks
in threads that read the data. A reading thread may still need to use snapshot/1
if a goal depends on multiple calls to dynamic predicates. Unlike locks,
transaction and snapshot based synchronization allows both readers and
writers to make progress simultaneously.81Read-write
locks also provide readers and writers to make progress simultaneously,
but readers see all intermediate states rather than a consistent state.
Transactions on their own do not guarantee consistency. For example, when running the code below to update the temperature concurrently from multiple threads it is possible for the global state to have multiple temperature/1 clauses.
update_temperature(Temp) :- transaction(( retractall(temperature(_)), asserta(temperature(Temp)))).
- Transactions allow for “what if'' reasoning over the dynamic database. This is particularly useful when combined with the deductive database facilities provided by tabling (see section 7).
SWI-Prolog transactions only affect the dynamic database. Static predicates are globally visible and shared at all times. In particular, transactions do not affect loading source files and thus, source files loaded inside a transaction (e.g., due