📄 atomiccommit.html
字号:
<h2>4.0 Rollback</h2><p>An atomic commit is suppose to happen instantaneously. But the processingdescribed above clearly takes a finite amount of time.Suppose the power to the computer were cutpart way through the commit operation described above. In orderto maintain the illusion that the changes were instantaneous, wehave to "rollback" any partial changes and restore the database tothe state it was in prior to the beginning of the transaction.</p><h3>4.1 When Something Goes Wrong...</h3><img src="images/ac/rollback-0.gif" align="right" hspace="15"><p>Suppose the power loss occurred during step 3.10 above,while the database changes were being written to disk.After power is restored, the situation might be somethinglike what is shown to the right. We were trying to changethree pages of the database file but only one page wassuccessfully written. Another page was partially writtenand a third page was not written at all.</p><p>The rollback journal is complete and intact on disk whenthe power is restored. This is a key point. The reason forthe flush operation in step 3.7 is to make absolutely sure thatall of the rollback journal is safely on nonvolatile storageprior to making any changes to the database file itself.</p><br clear="both"><a name="section_4_2"></a><h3>4.2 Hot Rollback Journals</h3><img src="images/ac/rollback-1.gif" align="right" hspace="15"><p>The first time that any SQLite process attempts to accessthe database file, it obtains a shared lock as described insection 3.2 above. But then it notices that there is a rollback journal file present. SQLite then checks to see ifthe rollback journal is a "hot journal". A hot journal isa rollback journal that needs to be played back in order torestore the database to a sane state. A hot journal onlyexists when an earlier process was in the middle of committinga transaction when it crashed or lost power.</p><p>A rollback journal is a "hot" journal if all of the followingare true:</p><ul><li>The rollback journal exist.<li>The rollback journal is not an empty file.<li>There is no reserved lock on the main database file.<li>The header of the rollback journal is well-formed and in particular has not been zeroed out.<li>The rollback journal does notcontain the name of a master journal file (see<a href="#section_5_5">section 5.5</a> below) or if doescontain the name of a master journal, then that master journalfile exists.</ul><p>The presence of a hot journal is our indicationthat a previous process was trying to commit a transaction butit aborted for some reason prior to the completion of thecommit. A hot journal means thatthe database file is in an inconsistent state and needs tobe repaired (by rollback) prior to being used.</p><br clear="both"><h3>4.3 Obtaining An Exclusive Lock On The Database</h3><img src="images/ac/rollback-2.gif" align="right" hspace="15"><p>The first step toward dealing with a hot journal is toobtain an exclusive lock on the database file. This prevents twoor more processes from trying to rollback the same hot journalat the same time.</p><br clear="both"><a name="section_4_4"></a><h3>4.4 Rolling Back Incomplete Changes</h3><img src="images/ac/rollback-3.gif" align="right" hspace="15"><p>Once a process obtains an exclusive lock, it is permittedto write to the database file. It then proceeds to read theoriginal content of pages out of the rollback journal and writethat content back to were it came from in the database file.Recall that the header of the rollback journal records the originalsize of the database file prior to the start of the abortedtransaction. SQLite uses this information to truncate thedatabase file back to its original size in cases where theincomplete transaction caused the database to grow. At theend of this step, the database should be the same size andcontain the same information as it did before the start ofthe aborted transaction.</p><br clear="both"><h3>4.5 Deleting The Hot Journal</h3><img src="images/ac/rollback-4.gif" align="right" hspace="15"><p>After all information in the rollback journal has beenplayed back into the database file (and flushed to disk in casewe encounter yet another power failure), the hot rollback journalcan be deleted.</p><p>As in <a href="#section_3_11">section 3.11</a>, the journalfile might be truncated to zero length or its header mightbe overwritten with zeros as an optimization on systems wheredeleting a file is expense. Either way, the journal is no long hot after this step.</p><br clear="both"><h3>4.6 Continue As If The Uncompleted Writes Had Never Happened</h3><img src="images/ac/rollback-5.gif" align="right" hspace="15"><p>The final recovery step is to reduce the exclusive lock backto a shared lock. Once this happens, the database is back in thestate that it would have been if the aborted transaction had neverstarted. Since all of this recovery activity happens completelyautomatically and transparently, it appears to the program usingSQLite as if the aborted transaction had never begun.</p><br clear="both"><h2>5.0 Multi-file Commit</h2><p>SQLite allows a single <a href="c3ref/sqlite3.html">database connection</a> to talk totwo or more database files simultaneously through the use ofthe <a href="lang_attach.html">ATTACH DATABASE</a> command.When multiple database files are modified within a singletransaction, all files are updated atomically. In other words, either all of the database files are updated orelse none of them are.Achieving an atomic commit across multiple database files ismore complex that doing so for a single file. This sectiondescribes how SQLite works that bit of magic.</p><h3>5.1 Separate Rollback Journals For Each Database</h3><img src="images/ac/multi-0.gif" align="right" hspace="15"><p>When multiple database files are involved in a transaction,each database has its own rollback journal and each databaseis locked separately. The diagram at the right shows a scenariowhere three different database files have been modified withinone transaction. The situation at this step is analogous to the single-file transaction scenario at <a href="#section_3_6">step 3.6</a>. Each database file hasa reserved lock. For each database, the original content of pages that are being changed have been written into the rollback journalfor that database, but the content of the journals have not yetbeen flushed to disk. No changes have been made to the databasefile itself yet, though presumably there are changes being heldin user memory.</p><p>For brevity, the diagrams in this section are simplified fromthose that came before. Blue color still signifies original contentand pink still signifies new content. But the individual pagesin the rollback journal and the database file are not shown andwe are not making the distinction between information in theoperating system cache and information that is on disk. All ofthese factors still apply in a multi-file commit scenario. Theyjust take up a lot of space in the diagrams and they do not addany new information, so they are omitted here.</p><br clear="both"><h3>5.2 The Master Journal File</h3><img src="images/ac/multi-1.gif" align="right" hspace="15"><p>The next step in a multi-file commit is the creation of a"master journal" file. The name of the master journal file isthe same name as the original database filename (the databasethat was opened using the <a href="c3ref/open.html">sqlite3_open()</a> interface,not one of the <a href="lang_attach.html">ATTACHed</a> auxiliarydatabases) with the text "<b>-mj</b><i>HHHHHHHH</i>" appended where<i>HHHHHHHH</i> is a random 32-bit hexadecimal number. Therandom <i>HHHHHHHH</i> suffix changes for every new master journal.</p><p><i>(Nota bene: The formula for computing the master journal filenamegiven in the previous paragraph corresponds to the implementation asof SQLite version 3.5.0. But this formula is not part of the SQLitespecification and is subject to change in future releases.)</i></p><p>Unlike the rollback journals, the master journal does not containany original database page content. Instead, the master journal containsthe full pathnames for rollback journals for every database that isparticipating in the transaction.</p><p>After the master journal is constructed, its content is flushedto disk before any further actions are taken. On unix, the directorythat contains the master journal is also synced in order to make surethe master journal file will appear in the directory following apower failure.</p><br clear="both"><h3>5.3 Updating Rollback Journal Headers</h3><img src="images/ac/multi-2.gif" align="right" hspace="15"><p>The next step is to record the full pathname of the master journal filein the header of every rollback journal. Space to hold the masterjournal filename was reserved at the beginning of each rollback journalas the rollback journals were created.</p><p>The content of each rollback journal is flushed to disk both beforeand after the master journal filename is written into the rollbackjournal header. It is important to do both of these flushes. Fortunately,the second flush is usually inexpensive since typically only a singlepage of the journal file (the first page) has changed.</p><p>This step is analogous to <a href="#section_3_7">step 3.7</a> in the single-file commitscenario described above.</p><br clear="both"><h3>5.4 Updating The Database Files</h3><img src="images/ac/multi-3.gif" align="right" hspace="15"><p>Once all rollback journal files have been flushed to disk, itis safe to begin updating database files. We have to obtain anexclusive lock on all database files before writing the changes.After all the changes are written, it is important to flush thechanges to disk so that they will be preserved in the event ofa power failure or operating system crash.</p><p>This step corresponds to steps<a href="#section_3_8">3.8</a>,<a href="#section_3_9">3.9</a>, and<a href="#section_3_10">3.10</a> in the single-file commitscenario described previously.</p><br clear="both"><a name="section_5_5"></a><h3>5.5 Delete The Master Journal File</h3><img src="images/ac/multi-4.gif" align="right" hspace="15"><p>The next step is to delete the master journal file.This is the point where the multi-file transaction commits.This step corresponds to <a href="#section_3_11">step 3.11</a> in the single-filecommit scenario where the rollback journal is deleted.</p><p>If a power failure or operating system crash occurs at thispoint, the transaction will not rollback when the system rebootseven though there are rollback journals present. Thedifference is the master journal pathname in the header of therollback journal. Upon restart, SQLite only considers a journalto be hot and will only playback the journal if there is nomaster journal filename in the header (which is the case fora single-file commit) or if the master journal file stillexists on disk.</p><br clear="both"><h3>5.6 Clean Up The Rollback Journals</h3><img src="images/ac/multi-5.gif" align="right" hspace="15"><p>The final step in a multi-file commit is to delete theindividual rollback journals and drop the exclusive locks onthe database files so that other processes can see the changes.This corresponds to <a href="#section_3_12">step 3.12</a> in the single-filecommit sequence.</p><p>The transaction has already committed at this point so timingis not critical in the deletion of the rollback journals.The current implementation deletes a single rollback journalthen unlocks the corresponding database file before proceedingto the next rollback journal. But in the future we might changethis so that all rollback journals are deleted before any databasefiles are unlocked. As long as the rollback journal is deleted beforeits corresponding database file is unlocked it does not matter in what
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -