如何使用Microsoft的API恢复/恢复ESE DB

时间:2016-11-06 11:51:37

标签: c++ database winapi extensible-storage-engine

我在这里基本上想要实现的是恢复脏数据库的正确方法。

esentutl /mh db.dat产生以下输出

enter image description here

这很好,因为我在被另一个程序打开时拿了一份数据库副本。

是否可以使用微软的JetBlue Api打开数据库而没有正确的日志& chk文件? ( ESEDatabaseView 以某种方式完成,nirsoft.net

如果使用Microsoft的API无法实现这种情况,并且需要日志,那么恢复数据库的正确方法是什么(我已经更改了我的数据库&和日志位置)

这是我的代码:

   wpath p2 = L"C:\\m.db";
        ULONG unPageSize;
        long jet_err = JetGetDatabaseFileInfoW(p2.file_string().c_str(), &unPageSize, sizeof(unPageSize), JET_DbInfoPageSize);
        if (jet_err != JET_errSuccess) {
            return false;
        }

        jet_err = JetSetSystemParameter( NULL, NULL, JET_paramDatabasePageSize, unPageSize, NULL);
        if (jet_err != JET_errSuccess) {
            return false;
        }

        jet_err = JetSetSystemParameter( NULL, NULL, JET_paramRecovery, 0, "Off");
        if (jet_err != JET_errSuccess) {
            return false;
        }

        jet_err = JetSetSystemParameter( NULL, NULL, JET_paramLogFilePath, 0, "C:\\");
        if (jet_err != JET_errSuccess) {
            return false;
        }

        jet_err = JetSetSystemParameter( NULL, NULL, JET_paramSystemPath, 0, "C:\\");
        if (jet_err != JET_errSuccess) {
            return false;
        }

        jet_err = JetSetSystemParameter( NULL, NULL, JET_paramAlternateDatabaseRecoveryPath, 0, "C:\\");
        if (jet_err != JET_errSuccess) {
            return false;
        }

        JET_INSTANCE instance = { 0 };
        jet_err = JetCreateInstance(&instance, "instance");
        if (jet_err != JET_errSuccess) {
            return false;
        }

        jet_err = JetInit(&instance);
        if (jet_err != JET_errSuccess) {
            JetTerm(instance);
            return false;
        }

        JET_SESID sesid;
        jet_err = JetBeginSession(instance, &sesid, 0, 0);
        if (jet_err != JET_errSuccess) {
            JetTerm(instance);
            return false;
        }

        jet_err = JetAttachDatabaseW( sesid, pathESEDbLocation.file_string().c_str(), JET_bitDbReadOnly);
        if (jet_err != JET_errSuccess) {
            JetEndSession(sesid, 0);
            JetTerm(instance);
            return false;
        }

JetAttachDatabaseW以-550 JET_errDatabaseDirtyShutdown

失败

编辑我发现没有任何检查点和日志文件的简单esenutl /p data.dat调用也解决了这个问题。我已尝试使用JetExternalRestoreW命令,但它不断抛出#define JET_errFileNotFound -1811 /* File not found */

JET_RSTMAP_W p = {L"C:/Users/user/AppData/Local/Temp/db/db.dat", L"C:/Users/user/AppData/Local/Temp/db/db.dat"};
jet_err = JetExternalRestoreW(nullptr, L"C:/Users/user/AppData/Local/Temp/db/", &p, 1,L"C:/Users/igalk/AppData/Local/Temp/db/",  0, 0, nullptr);

1 个答案:

答案 0 :(得分:0)

脏关机并不代表它缺少日志和检查文件......所以这可能是一个单独的问题。

你上面的例子有错误的顺序......

您可以将应用程序配置为自动尝试清除"脏关机"通过在JetCreateInstance之后和JetInit之前添加以下内容:

Api.JetSetSystemParameter(instance, JET_SESID.Nil, Server2003Param.AlternateDatabaseRecoveryPath, 0, Path.GetDirectoryName(databasePath));

(上面的示例是在C#中,但你明白了......)

最后一个参数是您希望修复数据库出现的位置,因此很可能与脏数据库文件位于同一目录。