📄 fileio.html
字号:
recovery. This includes regions of the sectors that were not actually modified by the write file operation.</p><p class=req id=A21011> If a system failure occurs on a system that supports the <i>atomic-write</i> property for blocks of size <i>N</i> bytes following an aligned write of <i>N</i> bytes to a file but before the file has been succesfully <i>synced</i>, then is is assumed following recovery that all sectors spanned by the write operation were correctly updated, or that none of the sectors were modified at all.</p><p class=req id=A21012> If a system failure occurs on a system that supports the <i>safe-append</i> following a write operation that appends data to the end of the file without modifying any of the existing file content but before the file has been succesfully <i>synced</i>, then is is assumed following recovery that either the data was correctly appended to the file, or that the file size remains unchanged. It is assumed that it is impossible that the file be extended but populated with incorrect data.</p><p class=req id=A21013> Following a system recovery, if a device sector is deemed to be untrustworthy as defined by A21008 and neither A21011 or A21012 apply to the range of bytes written, then no assumption can be made about the content of the sector following recovery. It is assumed that it is possible for such a sector to be written correctly, not written at all, populated with garbage data or any combination thereof.</p><p class=req id=A21009> If a system failure occurs during or after a "write file" operation that causes the file to grow, but before the corresponding file has been <i>synced</i>, then it is assumed that the size of the file following recovery is as large or larger than it was when it was most recently <i>synced</i>.</p> <p> If a system supports the <i>sequential-write</i> property, then further assumptions may be made with respect to the state of the file-system following recovery from a <i>system failure</i>. Specifically, it is assumed that create, truncate, delete and write file operations are applied to the persistent representation in the same order as they are performed by SQLite. Furthermore, it is assumed that the file-system waits until one operation is safely written to the persistent media before the next is attempted, just as if the relevant file were <i>synced</i> following each operation.<p class=req id=A21014> If a system failure occurs on a system that supports the <i>sequential-write</i> property, then it is assumed that all operations completed before the last time any file was <i>synced</i> have been successfully committed to persistent media.</p><p class=req id=A21015> If a system failure occurs on a system that supports the <i>sequential-write</i> property, then it is assumed that the set of possible states that the file-system may be in following recovery is the same as if each of the write operations performed since the most recent time a file was <i>synced</i> was itself followed by a <i>sync file</i> operation, and that the system failure may have occured during any of the write or <i>sync file</i> operations.</p><!-- <p> The return value of the xSectorSize() method, the <i>sector-size</i>, is expected by SQLite to be a power of 2 value greater than or equal to 512. <p class=todo> What does it do if this is not the case? If the sector size is less than 512 then 512 is used instead. How about a non power-of-two value? UPDATE: How this situation is handled should be described in the API requirements. Here we can just refer to the other document. <p> SQLite assumes that files are stored and written to within the file-system as a collection of blocks (hereafter sectors) of data, each <i>sector-size</i> bytes in size. This model is used to derive the following assumptions related to the expected state of the file-system following a power failure or operating system crash. <ul> <li> After part or all of a file sector has been modified using the xWrite() method of an open file-handle, the sector is said to be in a transient state, where the operating system makes no guarantees about the actual content of the sector on the persistent media. The sector remains in the transient state until the next successful call to xSync() on the same file-handle returns. If a power failure or operating system crash occurs, then part or all of all sectors in the transient state when the crash occured may contain invalid data following system recovery. <li> Following a power failure or operating system crash, the content of all sectors that were not in a transient state when the crash occured may be trusted. </ul> <p class=todo> What do we assume about the other three file-system write operations - xTruncate(), xDelete() and "create file"? <p> The xDeviceCharacteristics() method returns a set of flags, indicating which of the following properties (if any) the file-system provides: <ul> <li>The <b><i>sequential IO</i></b> property. If a file-system has this property, then in the event of a crash at most a single sector may contain invalid data. The file-system guarantees <li>The <b><i>safe-append</i></b> property. <li>The <b><i>atomic write</i></b> property. </ul> <p class=todo> Write an explanation as to how the file-system properties influence the model used to predict file damage after a catastrophy. --><h1 id=database_connections>Database Connections</h1> <p> Within this document, the term <i>database connection</i> has a slightly different meaning from that which one might assume. The handles returned by the <code>sqlite3_open()</code> and <code>sqlite3_open16()</code> APIs (<span class=todo>reference</span>) are referred to as <i>database handles</i>. A <i>database connection</i> is a connection to a single database file using a single file-handle, which is held open for the lifetime of the connection. Using the SQL ATTACH syntax, multiple <i>database connections</i> may be accessed via a single <i>database handle</i>. Or, using SQLite's <i>shared-cache mode</i> feature, multiple <i>database handles</i> may access a single <i>database connection</i>. <p> Usually, a new <i>database connection</i> is opened whenever the user opens new <i>database handle</i> on a real database file (not an in-memory database) or when a database file is attached to an existing <i>database connection</i> using the SQL ATTACH syntax. However if the <i>shared-cache mode</i> feature is enabled, then the database file may be accessed through an existing <i>database connection</i>. For more information on <i>shared-cache mode</i>, refer to <span class=todo>Reference</span>. The various IO operations required to open a new connection are detailed in section <cite>open_new_connection</cite> of this document. <p> Similarly, a <i>database connection</i> is usually closed when the user closes a <i>database handle</i> that is open on a real database file or has had one or more real database files attached to it using the ATTACH mechanism, or when a real database file is detached from a <i>database connection</i> using the DETACH syntax. Again, the exception is if <i>shared-cache mode</i> is enabled. In this case, a <i>database connection</i> is not closed until its number of users reaches zero. The IO related steps required to close a <i>database connection</i> are described in section <cite>closing_database_connection</cite>. <p class=todo> After sections 4 and 5 are finished, come back here and see if we can add a list of state items associated with each database connection to make things easier to understand. i.e each database connection has a file handle, a set of entries in the page cache, an expected page size etc. <h2 id=open_new_connection>Opening a New Connection</h2> <p> This section describes the VFS operations that take place when a new database connection is created. <p> Opening a new database connection is a two-step process: <ol> <li> A file-handle is opened on the database file. <li> If step 1 was successful, an attempt is made to read the <i>database file header</i> from the database file using the new file-handle. </ol> <p> In step 2 of the procedure above, the database file is not locked before it is read from. This is the only exception to the locking rules described in section <cite>reading_data</cite>. <p> The reason for attempting to read the <i>database file header</i> is to determine the <i>page-size</i> used by the database file. Because it is not possible to be certain as to the <i>page-size</i> without holding at least a <i>shared lock</i> on the database file (because some other <i>database connection</i> might have changed it since the <i>database file header</i> was read), the value read from the <i>database file header</i> is known as the <i>expected page size</i>. <p class=req id=H35060>When a new <i>database connection</i> is required, SQLite shall attemptto open a file-handle on the database file. If the attempt fails, thenno new <i>database connection</i> is created and an error returned.<p class=req id=H35070>When a new <i>database connection</i> is required, after opening thenew file-handle, SQLite shall attempt to read the first 100 bytesof the database file. If the attempt fails for any other reason thanthat the opened file is less than 100 bytes in size, thenthe file-handle is closed, no new <i>database connection</i> is createdand an error returned instead.<p class=req id=H35080>If the <i>database file header</i> is successfully read from a newlyopened database file, the connections <i>expected page-size</i> shallbe set to the value stored in the <i>page-size field</i> of thedatabase header.<p class=req id=H35090>If the <i>database file header</i> cannot be read from a newly openeddatabase file (because the file is less than 100 bytes in size), theconnections <i>expected page-size</i> shall be set to the compile timevalue of the SQLITE_DEFAULT_PAGESIZE option. <h2 id=closing_database_connection>Closing a Connection</h2> <p> This section describes the VFS operations that take place when an existing database connection is closed (destroyed). <p> Closing a database connection is a simple matter. The open VFS file-handle is closed and in-memory <i>page cache</i> related resources are released. <p class=req id=H35400>When a <i>database connection</i> is closed, SQLite shall close theassociated file handle at the VFS level.<p class=req id=H35430>When a <i>database connection</i> is closed, all associated <i>pagecache</i> entries shall be discarded.<h1 id=page_cache>The Page Cache</h1> <p> The contents of an SQLite database file are formatted as a set of fixed size pages. See <cite>ff_sqlitert_requirements</cite> for a complete description of the format used. The <i>page size</i> used for a particular database is stored as part of the database file header at a well-known offset within the first 100 bytes of the file. Almost all read and write operations performed by SQLite on database files are done on blocks of data <i>page-size</i> bytes in size. <p> All SQLite database connections running within a single process share a single <i>page cache</i>. The <i>page cache</i> caches data read from database files in main-memory on a per-page basis. When SQLite requires data from a database file to satisfy a database query, it checks the <i> page cache</i> for usable cached versions of the required database pages before loading it from the database file. If no usable cache entry can be found and the database page data is loaded from the database file, it is cached in the <i>page cache</i> in case the same data is needed again later. Because reading from the database file is assumed to be an order of magnitude faster than reading from main-memory, caching database page content in the <i>page cache</i> to minimize the number of read operations performed on the database file is a significant performance enhancement. <p> The <i>page cache</i> is also used to buffer database write operations. When SQLite is required to modify one of more of the <i>database pages</i> that make up a database file, it first modifies the cached version of the page in the <i>page cache</i>. At that point the page is considered a "dirty" page. At some point later on, the new content of the "dirty" page is copied from the <i>page cache</i> into the database file via the VFS interface. Buffering writes in the <i>page cache</i> can reduce the number of write operations required on the database file (in cases where the same page is updated twice) and allows optimizations based on the assumptions outlined in section <cite>fs_performance</cite>. <p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -