Collection Contents Previous Next PDF

UltraLite Database User's Guide

UltraLite Databases

The UltraLite runtime

Understanding concurrency in UltraLite


UltraLite databases may receive multiple concurrent requests. In order to design applications that handle concurrent requests properly you should understand how UltraLite manages concurrency in the database.

Concepts 

It is helpful to separate several concepts when thinking about concurrent database access. These concepts are ordered from high-level to low-level:

Multiple databases 

The UltraLite runtime can manage a maximum of four databases at any one time. A single UltraLite application may open multiple connections to separate databases. No concurrency issues arise from such applications, as the data in each database is independent.

Locking 

When a transaction changes a row, UltraLite locks that row until the transaction is committed or rolled back. The lock prevents other transactions from changing the row, although they can still read the row. An attempt to change a locked row sets error SQLCODE SQLE_LOCKED, while an attempt to change a deleted row sets the error SQLE_NOTFOUND. Your applications should check the SQLCODE value after attempting to modify data.

Re-reading rows 

To understand how locking and concurrency is managed, it helps to consider two connections, A and B, each with their own transaction.

As connection A works with the result set of a query, UltraLite fetches a copy of the current row into a buffer. If A modifies the current row, it changes the copy in the buffer. The copy in the buffer is written back into the database when connection A calls an Update method or closes the result set. At that time, a write lock is placed on the row to prevent other transactions from modifying it. The change to the database is not permanent until connection A commits the transaction.

Reading or fetching a row does not lock the row. If connection A fetches but does not modify a row, connection B can still modify the row.

If connection B does modify the current row, the row becomes locked. Connection A can then not modify the current row. If connection A fetches the current row again, and the row has been deleted, connection A gets the next row in the result set. If the row has been modified, connection A gets the latest copy of the row. If the columns of the index used by connection A have been modified, connection A sees the change as a delete followed by an insert, and so gets the next row in the result set.

Synchronization 

Synchronization behaves as a separate connection. During the upload phase, UltraLite applications can access UltraLite databases in a read-only fashion. During the download phase, read-write access is permitted but if an application changes a row that the download then attempts to change, the download will fail and roll back. You can disable access to data during synchronization by setting the Disable Concurrency synchronization parameter.

For more information, see Disable Concurrency synchronization parameter.


Collection Contents Previous Next PDF