Как начать несколько сеансов с Extensible Storage Engine

В документации для JetBeginSession, он отмечает, что сеанс является единицей гранулярности, которая определяет транзакцию, он определяет, где находится курсор в вашей текущей открытой таблице, он определяет текущий активный индекс. На одном сеансе ничего нельзя сделать. Но они отмечают:

Для повышения параллелизма и параллельного доступа к базе данных можно начать несколько сеансов.

Что я и хотел бы. Я хотел бы открыть второй сеанс для базы данных.

Фон

ESE несколько запутан в том, как вы это делаете:

JetCreateInstance(out instance, "UniqueInstanceName"); //Create a uniquely named instance of the ESE in our process

JetInit(instance); //initialize the instance
   JetBeginSession(instance, out sessionID); //initialize a session on the instance
      JetAttachDatabase(sessionID, filename); //attach a database file to our session
         JetOpenDatabase(sessionID, filename, "", out databaseID, 0); //open the database file in our session

            //...now we can open table, get data, etc
            //E.g. JetOpenTable(sessionID, databaseID, "Customers", null, 0, JET_bitTableReadOnly, out tableID);

         JetCloseDatabase(sessionID, databaseID);
      JetDetachDatabase(sessionID, filename);
   JetEndSession(sessionID, 0);
JetTerm(instance);

И это все работает.

Но как нам открыть еще одну сессию?

Документация ESE, хотя и редкая, намекает на возможность иметь несколько сеансов для одной и той же базы данных:

  • Для повышения параллелизма и параллельного доступа к базе данных можно начать несколько сеансов.
  • JET_bitTableDenyRead - Таблица не может быть открыта для чтения другим сеансом базы данных. (подразумевается, что иногда он может быть открыт для чтения другим сеансом)
  • JET_bitTableDenyWrite - Таблица не может быть открыта для доступа для записи другим сеансом базы данных. (подразумевается, что иногда он может быть открыт для доступа для записи другим сеансом)
  • JetOpenDatabase - Эта функция может вызываться несколько раз для одной и той же базы данных.
  • JET_bitDbExclusive - Позволяет только один сеанс присоединить базу данных. Обычно несколько сеансов могут открыть базу данных. (акцент мой)

Наивным подходом было бы начать еще одну сессию:

//Startup the instance
JetCreateInstance(out instance, "UniqueInstanceName");
JetInit(instance);

   //Make first session
   JetBeginSession(instance, out sessionID);
   JetAttachDatabase(sessionID, filename);
   JetOpenDatabase(sessionID, filename, "", out databaseID, 0);

      //Startup second session
      JetBeginSession(instance, out session2ID);
      JetAttachDatabase(session2ID, filename);
      JetOpenDatabase(session2ID, filename, "", out database2ID, 0);

      //Teardown second session
      JetCloseDatabase(session2ID, database2ID);
      JetDetachDatabase(session2ID, filename);  <----hangs
      JetEndSession(session2ID, 0);

   //Teardown first session
   JetCloseDatabase(sessionID, databaseID);
   JetDetachDatabase(sessionID, filename); 
   JetEndSession(sessionID, 0);

//Terminate instance
JetTerm(instance);

Кроме звонка JetDetachDatabase во второй сессии висит.

  • Проверка документации JetDetachDatabase не помогает
  • Проверка JetAttachDatabase мы сталкиваемся с чем-то тревожным.

Существует код ошибки, подразумевающий, что попытка присоединить базу данных, которая уже была присоединена к другому сеансу, является ошибкой:

JET_errDatabaseSharingViolation: файл базы данных уже был прикреплен другим сеансом.

Как открыть несколько сессий?

Так что теперь, вместо того, чтобы шататься слишком случайно, я попрошу правильный способ сделать это.

Как начать несколько сеансов с Extensible Storage Engine

бонус

Я колебался несколько случайно. Если звонок JetDetachDatabase висит, давайте просто не называть это! Это полностью нарушает документированные правила:

  • JetOpenDatabase говорит, что я должен позвонить JetAttachDatabase первый
  • JetAttachDatabase говорит, что я должен позвонить JetDetachDatabase

Но попробуем это:

//Startup the instance
JetCreateInstance(out instance, "UniqueInstanceName");
JetInit(instance);

   //Make first session
   JetBeginSession(instance, out sessionID);
   JetAttachDatabase(sessionID, filename);
   JetOpenDatabase(sessionID, filename, "", out databaseID, 0);

      //Startup second session
      JetBeginSession(instance, out session2ID);
      JetOpenDatabase(session2ID, filename, "", out database2ID, 0);

      //Teardown second session
      JetCloseDatabase(session2ID, database2ID);
      JetEndSession(session2ID, 0);

   //Teardown first session
   JetCloseDatabase(sessionID, databaseID);
   JetDetachDatabase(sessionID, filename); 
   JetEndSession(sessionID, 0);

//Terminate instance
JetTerm(instance);

И на самом деле кажется, что это работает.

...ура?

1 ответ

Решение

То, что вы сделали в своем "колебании", было правильным способом доступа к базе данных из нескольких сеансов.

JetAttachDatabase() открывает файл и связывает его с экземпляром. Это нужно вызвать только один раз.

JetOpenDatabase() открывает дескриптор базы данных в рамках сеанса и может вызываться при каждом сеансе.

Другие вопросы по тегам