在没有干净关闭的情况下附加ESE数据库

时间:2018-02-28 14:30:46

标签: extensible-storage-engine

我有一个ESE数据库(@Override public void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); // access data fragment final FragmentManager fm = getFragmentManager(); this.myDataFragment = (MyDataFragment)fm.findFragmentByTag(MyActivity.MY_DATA_FRAGMENT); } private void function1 () { // read data from data Fragment String dataStr = this.myDataFragment.myData; // write data into data Fragment this.myDataFragment.myData = "test_string"; } private MyDataFragment myDataFragment = null; ),我从一个正在使用的应用程序中复制了该数据库。当然,这意味着数据库处于“脏关闭”状态。幸运的是,我确实拥有数据库的日志文件("Vulcan.edb"),根据every similar question我可以找到,我应该能够附加数据库并拥有引擎恢复它。以下是我用来附加数据库的代码,使用托管ESE API(非托管C ++端口应该是微不足道的):

"V01.log"

实际上,如果我将数据库文件和日志文件都复制到public void ReadFromDatabase(string fileName, string logFileBaseName) { string databaseDirectory = Path.GetDirectoryName(fileName); int pageSize; Api.JetGetDatabaseFileInfo(fileName, out pageSize, JET_DbInfo.PageSize); Api.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, JET_param.DatabasePageSize, pageSize, null); Api.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, JET_param.Recovery, 0, "Off"); JET_INSTANCE jetInstance; string jetInstanceName = Guid.NewGuid().ToString("N"); Api.JetCreateInstance(out jetInstance, jetInstanceName); Api.JetSetSystemParameter(jetInstance, JET_SESID.Nil, JET_param.BaseName, 0, logFileBaseName); Api.JetSetSystemParameter(jetInstance, JET_SESID.Nil, JET_param.LogFilePath, 0, databaseDirectory); Api.JetSetSystemParameter(jetInstance, JET_SESID.Nil, JET_param.TempPath, 0, databaseDirectory); Api.JetSetSystemParameter(jetInstance, JET_SESID.Nil, JET_param.SystemPath, 0, databaseDirectory); Api.JetSetSystemParameter(jetInstance, JET_SESID.Nil, Microsoft.Isam.Esent.Interop.Server2003.Server2003Param.AlternateDatabaseRecoveryPath, 0, databaseDirectory); try { Api.JetInit(ref jetInstance); JET_SESID sessionId; Api.JetBeginSession(jetInstance, out sessionId, "admin", ""); try { Api.JetAttachDatabase(sessionId, fileName, AttachDatabaseGrbit.ReadOnly); JET_DBID databaseId; Api.JetOpenDatabase(sessionId, fileName, "", out databaseId, OpenDatabaseGrbit.ReadOnly); // Do other stuff here... Api.JetCloseDatabase(sessionId, databaseId, CloseDatabaseGrbit.None); } finally { Api.JetEndSession(sessionId, EndSessionGrbit.None); } } finally { Api.JetTerm(jetInstance); } } 并运行 <directory of database>, 数据库在我的代码中呈现可用和可附加。但是,如果我不采取手动恢复数据库的步骤,我的代码无法调用edbntutl.exe /r V01 /l <directory of database> /s <directory of database> /d <directory of database>,错误为JetAttachDatabase

那为什么我的代码不能自动恢复数据库呢? JET_errDatabaseDirtyShutdown正在做一些未记录的事情,或者我在会话配置中遗漏了某些内容以允许引擎恢复数据库。虽然前者不是不可能的,但如果是这样的话,那将是非常不幸的,而且我倾向于相信我只是错过了一些东西。

注意:如果没有证据表明该实用程序正在执行公共API中没有的操作,那么相当于“在运行代码之前运行esentutil”的答案将不会被接受为正确。

1 个答案:

答案 0 :(得分:0)

你需要做一些事情来强有力地处理esent dbs的加载。 以下是从RavenDB代码库中处理脏关闭所需的相关代码:

https://github.com/ravendb/ravendb/blob/552208aed679f4a3936a57f9a7506568657e291e/Raven.Database/Storage/Esent/TransactionalStorage.cs#L721-L736