前端之家收集整理的这篇文章主要介绍了
SQLite入门与分析(四)---Page Cache之事务处理3,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
11、删除日志文件(Deleting The Rollback Journal)
一旦更改写入设备,日志文件将会被删除,这是事务真正提交的时刻。如果在这之前系统发生崩溃,就会进行恢复处理,使得数据库和没发生改变一样;如果在这之后系统发生崩溃,表明所有的更改都已经写入磁盘。sqlite就是根据日志存在情况决定是否对数据库进行恢复处理。
删除文件本质上不是一个原子操作,但是从用户进程的角度来看是一个原子操作,所以一个事务看起来是一个原子操作。
在许多系统中,删除文件也是一个高代价的操作。作为优化,sqlite可以配置成把日志文件的长度截为0或者把日志文件头清零。
12、释放锁(Releasing The Lock)
作为原子提交的最后一步,释放排斥锁使得其它进程可以开始访问数据库了。
下图中,我们指明了当锁被释放的时候用户空间所拥有的信息已经被清空了.对于老版本的sqlite你可这么认为。但最新的sqlite会保存些用户空间的缓存不会被清空—万一下一个事务开始的时候,这些数据刚好可以用上呢。重新利用这些内存要比再次从操作系统磁盘缓存或者硬盘中读取要来得轻松与快捷得多,何乐而不为呢?在再次使用这些数据之前,我们必须先取得一个共享锁,同时我们还不得不去检查一下,保证还没有其他进程在我们拥有共享锁之前对数据库文件进行了修改。数据库文件的第一页中有一个计数器,数据库文件每做一次修改,这个计数器就会增长一下。我们可以通过检查这个计数器就可得知是否有其他进程修改过数据库文件。如果数据库文件已经被修改过了,那么用户内存空间的缓存就不得不清空,并重新读入。大多数情况下,这种情况不大会发生,因此用户空间的内存缓存将是有效的,这对于性能提高来说作用是显著的。
以上两步是在sqlite3BtreeCommit()---btree.c函数中实现的。
代码如下:
@H_
404_38@
Code
//提交事务,至此一个事务完成.主要做两件事:
//删除日志文件,释放数据库文件的写锁
intsqlite3BtreeCommit(Btree*p){
BtShared*pBt=p->pBt;
btreeIntegrity(p);
/*Ifthehandlehasawrite-transactionopen,committheshared-btrees
**transactionandsetthesharedstatetoTRANS_READ.
*/
if(p->inTrans==TRANS_WRITE){
intrc;
assert(pBt->inTransaction==TRANS_WRITE);
assert(pBt->nTransaction>0);
//调用pager,提交事务
rc=sqlite3pager_commit(pBt->pPager);
if(rc!=sqlITE_OK){
returnrc;
}
pBt->inTransaction=TRANS_READ;
pBt->inStmt=0;
}
unlockAllTables(p);
/*Ifthehandlehasanykindoftransactionopen,decrementthetransaction
**countofthesharedbtree.Ifthetransactioncountreaches0,set
**thesharedstatetoTRANS_NONE.TheunlockBtreeIfUnused()callbelow
**willunlockthepager.
*/
if(p->inTrans!=TRANS_NONE){
pBt->nTransaction--;
if(0==pBt->nTransaction){
pBt->inTransaction=TRANS_NONE;
}
}
}
//提交事务,主要调用pager_unwritelock()函数
intsqlite3pager_commit(Pager*pPager){
intrc;
PgHdr*pPg;
if(pPager->errCode){
returnpPager->errCode;
}
if(pPager->state<PAGER_RESERVED){
returnsqlITE_ERROR;
}
TRACE2("COMMIT%d/n",PAGERID(pPager));
if(MEMDB){
pPg=pager_get_all_dirty_pages(pPager);
while(pPg){
clearHistory(PGHDR_TO_HIST(pPg,pPager));
pPg->dirty=0;
pPg->inJournal=0;
pPg->inStmt=0;
pPg->needSync=0;
pPg->pPrevStmt=pPg->pNextStmt=0;
pPg=pPg->pDirty;
}
pPager->pDirty=0;
#ifndefNDEBUG
for(pPg=pPager->pAll;pPg;pPg=pPg->pNextAll){
PgHistory*pHist=PGHDR_TO_HIST(pPg,pPager);
assert(!pPg->alwaysRollback);
assert(!pHist->pOrig);
assert(!pHist->pStmt);
}
#endif
pPager->pStmt=0;
pPager->state=PAGER_SHARED;
returnsqlITE_OK;
}
if(pPager->dirtyCache==0){
/*Exitearly(withoutdoingthetime-consumingsqlite3OsSync()calls)
**iftherehavebeennochangestothedatabasefile.*/
assert(pPager->needSync==0);
rc=pager_unwritelock(pPager);
pPager->dbSize=-1;
returnrc;
}
assert(pPager->journalOpen);
rc=sqlite3pager_sync(pPager,0,0);
//删除文件,释放写锁
if(rc==sqlITE_OK){
rc=pager_unwritelock(pPager);
pPager->dbSize=-1;
}
returnrc;
}
//对数据库加readlock,删除日志文件
staticintpager_unwritelock(Pager*pPager){
PgHdr*pPg;
intrc;
assert(!MEMDB);
if(pPager->state<PAGER_RESERVED){
returnsqlITE_OK;
}
sqlite3pager_stmt_commit(pPager);
if(pPager->stmtOpen){
sqlite3OsClose(&pPager->stfd);
pPager->stmtOpen=0;
}
if(pPager->journalOpen){
//关闭日志文件
sqlite3OsClose(&pPager->jfd);
pPager->journalOpen=0;
//删除日志文件
sqlite3OsDelete(pPager->zJournal);
sqliteFree(pPager->aInJournal);
pPager->aInJournal=0;
for(pPg=pPager->pAll;pPg;pPg=pPg->pNextAll){
pPg->inJournal=0;
pPg->dirty=0;
pPg->needSync=0;
#ifdefsqlITE_CHECK_PAGES
pPg->pageHash=pager_pagehash(pPg);
#endif
}
pPager->pDirty=0;
pPager->dirtyCache=0;
pPager->nRec=0;
}else{
assert(pPager->aInJournal==0);
assert(pPager->dirtyCache==0||pPager->useJournal==0);
}
//释放写锁,加读锁
rc=sqlite3OsUnlock(pPager->fd,SHARED_LOCK);
pPager->state=PAGER_SHARED;
pPager->origDbSize=0;
pPager->setMaster=0;
pPager->needSync=0;
pPager->pFirstSynced=pPager->pFirst;
returnrc;
}