1NOTE (2012-11-29): 2 3The functionality implemented by this extension has been superseded 4by WAL-mode. This module is no longer supported or maintained. The 5code is retained for historical reference only. 6 7------------------------------------------------------------------------------ 8 9Normally, when SQLite writes to a database file, it waits until the write 10operation is finished before returning control to the calling application. 11Since writing to the file-system is usually very slow compared with CPU 12bound operations, this can be a performance bottleneck. This directory 13contains an extension that causes SQLite to perform all write requests 14using a separate thread running in the background. Although this does not 15reduce the overall system resources (CPU, disk bandwidth etc.) at all, it 16allows SQLite to return control to the caller quickly even when writing to 17the database, eliminating the bottleneck. 18 19 1. Functionality 20 21 1.1 How it Works 22 1.2 Limitations 23 1.3 Locking and Concurrency 24 25 2. Compilation and Usage 26 27 3. Porting 28 29 30 311. FUNCTIONALITY 32 33 With asynchronous I/O, write requests are handled by a separate thread 34 running in the background. This means that the thread that initiates 35 a database write does not have to wait for (sometimes slow) disk I/O 36 to occur. The write seems to happen very quickly, though in reality 37 it is happening at its usual slow pace in the background. 38 39 Asynchronous I/O appears to give better responsiveness, but at a price. 40 You lose the Durable property. With the default I/O backend of SQLite, 41 once a write completes, you know that the information you wrote is 42 safely on disk. With the asynchronous I/O, this is not the case. If 43 your program crashes or if a power loss occurs after the database 44 write but before the asynchronous write thread has completed, then the 45 database change might never make it to disk and the next user of the 46 database might not see your change. 47 48 You lose Durability with asynchronous I/O, but you still retain the 49 other parts of ACID: Atomic, Consistent, and Isolated. Many 50 appliations get along fine without the Durablity. 51 52 1.1 How it Works 53 54 Asynchronous I/O works by creating a special SQLite "vfs" structure 55 and registering it with sqlite3_vfs_register(). When files opened via 56 this vfs are written to (using the vfs xWrite() method), the data is not 57 written directly to disk, but is placed in the "write-queue" to be 58 handled by the background thread. 59 60 When files opened with the asynchronous vfs are read from 61 (using the vfs xRead() method), the data is read from the file on 62 disk and the write-queue, so that from the point of view of 63 the vfs reader the xWrite() appears to have already completed. 64 65 The special vfs is registered (and unregistered) by calls to the 66 API functions sqlite3async_initialize() and sqlite3async_shutdown(). 67 See section "Compilation and Usage" below for details. 68 69 1.2 Limitations 70 71 In order to gain experience with the main ideas surrounding asynchronous 72 IO, this implementation is deliberately kept simple. Additional 73 capabilities may be added in the future. 74 75 For example, as currently implemented, if writes are happening at a 76 steady stream that exceeds the I/O capability of the background writer 77 thread, the queue of pending write operations will grow without bound. 78 If this goes on for long enough, the host system could run out of memory. 79 A more sophisticated module could to keep track of the quantity of 80 pending writes and stop accepting new write requests when the queue of 81 pending writes grows too large. 82 83 1.3 Locking and Concurrency 84 85 Multiple connections from within a single process that use this 86 implementation of asynchronous IO may access a single database 87 file concurrently. From the point of view of the user, if all 88 connections are from within a single process, there is no difference 89 between the concurrency offered by "normal" SQLite and SQLite 90 using the asynchronous backend. 91 92 If file-locking is enabled (it is enabled by default), then connections 93 from multiple processes may also read and write the database file. 94 However concurrency is reduced as follows: 95 96 * When a connection using asynchronous IO begins a database 97 transaction, the database is locked immediately. However the 98 lock is not released until after all relevant operations 99 in the write-queue have been flushed to disk. This means 100 (for example) that the database may remain locked for some 101 time after a "COMMIT" or "ROLLBACK" is issued. 102 103 * If an application using asynchronous IO executes transactions 104 in quick succession, other database users may be effectively 105 locked out of the database. This is because when a BEGIN 106 is executed, a database lock is established immediately. But 107 when the corresponding COMMIT or ROLLBACK occurs, the lock 108 is not released until the relevant part of the write-queue 109 has been flushed through. As a result, if a COMMIT is followed 110 by a BEGIN before the write-queue is flushed through, the database 111 is never unlocked,preventing other processes from accessing 112 the database. 113 114 File-locking may be disabled at runtime using the sqlite3async_control() 115 API (see below). This may improve performance when an NFS or other 116 network file-system, as the synchronous round-trips to the server be 117 required to establish file locks are avoided. However, if multiple 118 connections attempt to access the same database file when file-locking 119 is disabled, application crashes and database corruption is a likely 120 outcome. 121 122 1232. COMPILATION AND USAGE 124 125 The asynchronous IO extension consists of a single file of C code 126 (sqlite3async.c), and a header file (sqlite3async.h) that defines the 127 C API used by applications to activate and control the modules 128 functionality. 129 130 To use the asynchronous IO extension, compile sqlite3async.c as 131 part of the application that uses SQLite. Then use the API defined 132 in sqlite3async.h to initialize and configure the module. 133 134 The asynchronous IO VFS API is described in detail in comments in 135 sqlite3async.h. Using the API usually consists of the following steps: 136 137 1. Register the asynchronous IO VFS with SQLite by calling the 138 sqlite3async_initialize() function. 139 140 2. Create a background thread to perform write operations and call 141 sqlite3async_run(). 142 143 3. Use the normal SQLite API to read and write to databases via 144 the asynchronous IO VFS. 145 146 Refer to sqlite3async.h for details. 147 148 1493. PORTING 150 151 Currently the asynchronous IO extension is compatible with win32 systems 152 and systems that support the pthreads interface, including Mac OSX, Linux, 153 and other varieties of Unix. 154 155 To port the asynchronous IO extension to another platform, the user must 156 implement mutex and condition variable primitives for the new platform. 157 Currently there is no externally available interface to allow this, but 158 modifying the code within sqlite3async.c to include the new platforms 159 concurrency primitives is relatively easy. Search within sqlite3async.c 160 for the comment string "PORTING FUNCTIONS" for details. Then implement 161 new versions of each of the following: 162 163 static void async_mutex_enter(int eMutex); 164 static void async_mutex_leave(int eMutex); 165 static void async_cond_wait(int eCond, int eMutex); 166 static void async_cond_signal(int eCond); 167 static void async_sched_yield(void); 168 169 The functionality required of each of the above functions is described 170 in comments in sqlite3async.c. 171