📄 fileio.html
字号:
requirement H35240. <h3 id=hot_journal_detection>Hot Journal Detection</h3> <p> This section describes the procedure that SQLite uses to detect a <i>hot journal file</i>. If a <i>hot journal file</i> is detected, this indicates that at some point the process of writing a transaction to the database was interrupted and a recovery operation (<i>hot journal rollback</i>) needs to take place. This section does not describe the process of <i>hot journal rollback</i> (see section <cite>hot_journal_rollback</cite>) or the processes by which a <i>hot journal file</i> may be created (see section <cite>writing_data</cite>). <p> The procedure used to detect a <i>hot-journal file</i> is quite complex. The following steps take place: <ol class=spacedlist> <li>Using the VFS xAccess() method, SQLite queries the file-system to see if the journal file associated with the database exists. If it does not, then there is no hot-journal file. <li>By invoking the xCheckReservedLock() method of the file-handle opened on the database file, SQLite checks if some other connection holds a <i>reserved lock</i> or greater. If some other connection does hold a <i>reserved lock</i>, this indicates that the other connection is midway through a <i>read/write transaction</i> (see section <cite>writing_data</cite>). In this case the <i>journal file</i> is not a <i>hot-journal</i> and must not be rolled back. <li>Using the xFileSize() method of the file-handle opened on the database file, SQLite checks if the database file is 0 bytes in size. If it is, the journal file is not considered to be a <i>hot journal</i> file. Instead of rolling back the journal file, in this case it is deleted from the file-system by calling the VFS xDelete() method. <span class=todo>Technically, there is a race condition here. This step should be moved to after the exclusive lock is held.</span> <li>An attempt is made to upgrade to an <i>exclusive lock</i> on the database file. If the attempt fails, then all locks, including the recently obtained <i>shared lock</i> are dropped. The attempt to open a <i>read-only transaction</i> has failed. This occurs when some other connection is also attempting to open a <i>read-only transaction</i> and the attempt to gain the <i>exclusive lock</i> fails because the other connection is also holding a <i>shared lock</i>. It is left to the other connection to roll back the <i>hot journal</i>. <div style="margin-top:0.5em"></div> It is important that the file-handle lock is upgraded directly from <i>shared</i> to <i>exclusive</i> in this case, instead of first upgrading to <i>reserved</i> or </i>pending</i> locks as is required when obtaining an <i>exclusive lock</i> to write to the database file (section <cite>writing_data</cite>). If SQLite were to first upgrade to a <i>reserved</i> or <i>pending</i> lock in this scenario, then a second process also trying to open a <i>read-transaction</i> on the database file might detect the <i>reserved</i> lock in step 2 of this process, conclude that there was no <i>hot journal</i>, and commence reading data from the <i>database file</i>. <li>The xAccess() method is invoked again to detect if the journal file is still in the file system. If it is, then it is a hot-journal file and SQLite tries to roll it back (see section <cite>rollback</cite>). </ol> <p class=todo> Master journal file pointers? <p> The following requirements describe step 1 of the above procedure in more detail.<p class=req id=H35140>When required to attempt to detect a <i>hot-journal file</i>, SQLiteshall first use the xAccess() method of the VFS layer to check if ajournal file exists in the file-system.<p class=req id=H35510>If the call to xAccess() required by H35140 fails (due to an IO error orsimilar), then SQLite shall abandon the attempt to open a <i>read-onlytransaction</i>, relinquish the <i>shared lock</i> held on the databasefile and return an error to the user.<p class=req id=H35150>When required to attempt to detect a <i>hot-journal file</i>, if thecall to xAccess() required by H35140 indicates that a journal file doesnot exist, then SQLite shall conclude that there is no <i>hot-journalfile</i> in the file system and therefore that no <i>hot journalrollback</i> is required. <p> The following requirements describe step 2 of the above procedure in more detail.<p class=req id=H35160>When required to attempt to detect a <i>hot-journal file</i>, if thecall to xAccess() required by H35140 indicates that a journal fileis present, then the xCheckReservedLock() method of the database filefile-handle is invoked to determine whether or not some otherprocess is holding a <i>reserved</i> or greater lock on the databasefile.<p class=req id=H35520>If the call to xCheckReservedLock() required by H35160 fails (due to anIO or other internal VFS error), then SQLite shall abandon the attemptto open a <i>read-only transaction</i>, relinquish the <i>shared lock</i>held on the database file and return an error to the user.<p class=req id=H35170>If the call to xCheckReservedLock() required by H35160 indicates thatsome other <i>database connection</i> is holding a <i>reserved</i>or greater lock on the database file, then SQLite shall conclude thatthere is no <i>hot journal file</i>. In this case the attempt to detecta <i>hot journal file</i> is concluded. <p> The following requirements describe step 3 of the above procedure in more detail.<p class=req id=H35440>If while attempting to detect a <i>hot-journal file</i> the call toxCheckReservedLock() indicates that no process holds a <i>reserved</i>or greater lock on the <i>database file</i>, then SQLite shall opena file handle on the potentially hot journal file using the VFS xOpen()method.<p class=req id=H35530>If the call to xOpen() required by H35440 fails (due to an IO or otherinternal VFS error), then SQLite shall abandon the attempt to open a<i>read-only transaction</i>, relinquish the <i>shared lock</i> held onthe database file and return an error to the user.<p class=req id=H35450>After successfully opening a file-handle on a potentially hot journalfile, SQLite shall query the file for its size in bytes using thexFileSize() method of the open file handle.<p class=req id=H35540>If the call to xFileSize() required by H35450 fails (due to an IO orother internal VFS error), then SQLite shall abandon the attempt to opena <i>read-only transaction</i>, relinquish the <i>shared lock</i> held onthe database file, close the file handle opened on the journal file andreturn an error to the user.<p class=req id=H35460>If the size of a potentially hot journal file is revealed to be zerobytes by a query required by H35450, then SQLite shall close thefile handle opened on the journal file and delete the journal file usinga call to the VFS xDelete() method. In this case SQLite shall concludethat there is no <i>hot journal file</i>.<p class=req id=H35550>If the call to xDelete() required by H35450 fails (due to an IO orother internal VFS error), then SQLite shall abandon the attempt to opena <i>read-only transaction</i>, relinquish the <i>shared lock</i> held onthe database file and return an error to the user. <p> The following requirements describe step 4 of the above procedure in more detail.<p class=req id=H35470>If the size of a potentially hot journal file is revealed to be greaterthan zero bytes by a query required by H35450, then SQLite shall attemptto upgrade the <i>shared lock</i> held by the <i>database connection</i>on the <i>database file</i> directly to an <i>exclusive lock</i>.<p class=req id=H35480>If an attempt to upgrade to an <i>exclusive lock</i> prescribed byH35470 fails for any reason, then SQLite shall release all locks held bythe <i>database connection</i> and close the file handle opened on the<i>journal file</i>. The attempt to open a <i>read-only transaction</i>shall be deemed to have failed and an error returned to the user. <p> Finally, the following requirements describe step 5 of the above procedure in more detail.<p class=req id=H35490>If, as part of the <i>hot journal file</i> detection process, theattempt to upgrade to an <i>exclusive lock</i> mandated by H35470 issuccessful, then SQLite shall query the file-system using the xAccess()method of the VFS implementation to test whether or not the journalfile is still present in the file-system.<p class=req id=H35560>If the call to xAccess() required by H35490 fails (due to an IO orother internal VFS error), then SQLite shall abandon the attempt to opena <i>read-only transaction</i>, relinquish the lock held on thedatabase file, close the file handle opened on the journal file andreturn an error to the user.<p class=req id=H35570>If the call to xAccess() required by H35490 reveals that the journalfile is no longer present in the file system, then SQLite shall abandonthe attempt to open a <i>read-only transaction</i>, relinquish thelock held on the database file, close the file handle opened on thejournal file and return an SQLITE_BUSY error to the user.<p class=req id=H35500>If the xAccess() query required by H35490 reveals that the journalfile is still present in the file system, then SQLite shall concludethat the journal file is a <i>hot journal file</i> that needs tobe rolled back. SQLite shall immediately begin <i>hot journalrollback</i>. <h3 id=cache_validation>Cache Validation</h3> <p> When a <i>database connection</i> opens a <i>read transaction</i>, the <i>page cache</i> may already contain data associated with the <i>database connection</i>. However, if another process has modified the database file since the cached pages were loaded it is possible that the cached data is invalid. <p> SQLite determines whether or not the <i>page cache</i> entries belonging to the <i>database connection</i> are valid or not using the <i>file change counter</i>, a field in the <i>database file header</i>. The <i>file change counter</i> is a 4-byte big-endian integer field stored starting at byte offset 24 of the <i>database file header</i>. Before the conclusion of a <i>read/write transaction</i> that modifies the contents of the database file in any way (see section <cite>writing_data</cite>), the value stored in the <i>file change counter</i> is incremented. When a <i>database connection</i> unlocks the database file, it stores the current value of the <i>file change counter</i>. Later, while opening a new <i>read-only transaction</i>, SQLite checks the value of the <i>file change counter</i> stored in the database file. If the value has not changed since the database file was unlocked, then the <i>page cache</i> entries can be trusted. If the value has changed, then the <i>page cache</i> entries cannot be trusted and all entries associated with the current <i>database connection</i> are discarded.<p class=req id=H35180>When a file-handle open on a database file is unlocked, if the<i>page cache</i> contains one or more entries belonging to theassociated <i>database connection</i>, SQLite shall store the valueof the <i>file change counter</i> internally.<p class=req id=H35190>When required to perform <i>cache validation</i> as part of openinga <i>read transaction</i>, SQLite shall read a 16 byte blockstarting at byte offset 24 of the <i>database file</i> using the xRead()method of the <i>database connections</i> file handle. <p class=todo> Why a 16 byte block? Why not 4? (something to do with encrypted databases).<p class=req id=H35200>While performing <i>cache validation</i>, after loading the 16 byteblock as required by H35190, SQLite shall compare the 32-bit big-endianinteger stored in the first 4 bytes of the block to the mostrecently stored value of the <i>file change counter</i> (see H35180).If the values are not the same, then SQLite shall conclude thatthe contents of the cache are invalid. <p> Requirement H35050 (section <cite>open_read_only_trans</cite>) specifies the action SQLite is required to take upon determining that the cache contents are invalid. <h3 id=read_page_one>Page 1 and the Expected Page Size</h3> <p> As the last step in opening a <i>read transaction</i> on a database file that is more than 0 bytes in size, SQLite is required to load data for page 1 of the database into the <i>page cache</i>, if it is not already there. This is slightly more complicated than it seems, as the database <i>page-size</i> is no known at this point. <p> Even though the database <i>page-size
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -