如何使用可扩展存储引擎开始多个会话

How to begin multiple sessions with Extensible Storage Engine

JetBeginSession 的文档中,它指出 session 是定义事务的粒度单位,它定义了游标所在的位置在您当前打开的 table 中,它定义了当前活动的索引。在一个 session 上没有别的可以做。但他们确实注意到:

To increase concurrency and parallel access to the database, multiple sessions can be begun.

这是我想要的。我想打开第二个 session 到数据库。

背景

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);

一切正常。

但是我们如何打开另一个session?

ESE 文档虽然稀疏,但确实暗示了可以让多个 session 用于同一数据库的能力:

  • To increase concurrency and parallel access to the database, multiple sessions can be begun.
  • JET_bitTableDenyRead - The table cannot be opened for read-access by another database session. (implying that sometimes it can be opened for read-access by another session)
  • JET_bitTableDenyWrite - The table cannot be opened for write-access by another database session. (implying that sometimes it can be opened for write-access by another session)
  • JetOpenDatabase - This function can be called multiple times for the same database.
  • JET_bitDbExclusive - Allows only a single session to attach a database. Normally, several sessions can open a database. (emphasis mine)

天真的方法是开始另一个 session:

//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);

除了在第二个 session 中对 JetDetachDatabase 的调用挂起。

有一个错误代码,暗示尝试附加一个已经被不同的数据库附加的数据库是错误的 session:

JET_errDatabaseSharingViolation: The database file has already been attached by a different session.

如何打开多个session?

所以现在,与其胡思乱想,不如问问正确的方法。

How to begin multiple sessions with Extensible Storage Engine

奖金

我确实有点随机地连枷。如果对 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);

它实际上似乎喜欢它碰巧工作。

...是吗?

您在 "flailing" 中所做的是从多个会话访问数据库的正确方法。

JetAttachDatabase() 打开文件并将其与实例相关联。只需调用一次。

JetOpenDatabase() 在会话中打开一个数据库句柄,并且可以在每个会话中调用。