事务管理器
对于多任务和/或多进程应用程序,或者在多用户环境中,如果有多个线程或进程可能更新数据库表,选择合适的事务管理器就显得尤为重要。而在单用户/单线程的应用场景中,如果只有一个应用程序线程访问数据库,那么并发问题不会出现,选择也很简单:使用独占(EXCLUSIVE)事务管理器。
有关并发控制的详细信息,请参阅“并发”页面。该页面提供了关于“事务隔离”级别的定义和解释。简而言之,SmartEDB 根据链接到应用程序的事务管理器提供“悲观”和“乐观”两种并发控制策略。MURSIW(多读单写)通过实施“可串行化”隔离级别来实现“悲观”并发管理。如果您希望采用更“乐观”的并发管理策略,例如“已读提交”或“可重复读”隔离级别,则需要将应用程序与 MVCC(多版本并发控制)事务管理器链接。
此外,还有一种专门针对“以读取为主”的数据访问模式优化性能的“优先读取”事务管理器,适用于读操作频繁的应用场景。
独占(EXCLUSIVE)事务管理器
这是最适合单用户/单线程应用程序的最高效事务管理器。它一次只允许一个任务访问数据库进行读取或写入操作。要使用 EXCLUSIVE 事务管理器,应用程序需要与库 mcotexcl 链接。
MURSIW 事务管理器
如前所述,MURSIW 事务管理器强制执行“可串行化”隔离级别,这意味着所有写入事务都会应用排他锁——在同一时间不能有其他写入事务运行。然而,“读取者”仍可以与“写入者”以及彼此并行运行。要选择 MURSIW 事务管理器,应用程序只需链接到库 mcotmursiw 即可。
MVCC 事务管理器
MVCC 事务管理器允许开发人员在调用 beginTransaction() 时通过指定 MCO_READ_COMMITTED 或 MCO_REPEATABLE_READ 来选择两种“乐观”隔离级别之一,或者通过指定 MCO_SERIALIZABLE 来选择“悲观”隔离级别。要选择隔离级别,应用程序必须与 MVCC 库 mcotmvcc 链接。
以下代码片段展示了在 SmartESQL 应用程序中如何指定隔离级别:
void task( McoSqlEngine & engine, _Person* p )
{
int rc;
uint4 i;
McoSqlSession session( engine );
Transaction* trans = session.database()->beginTransaction(Transaction::ReadWrite,
0, MCO_READ_REPEATABLE);
rc = session.executeStatement(trans, "insert into Persons %r", p);
sample_sleep(nap_duration2);
trans->commit();
trans->release();
}
在上述代码片段中,有几点编程细节需要注意:
McoSqlSession 类的使用:McoSqlSession 类用于通过当前的 SQL 数据库连接创建一个新的会话(线程)。这是必要的,因为在实例化 McoSqlEngine 时,主线程会自动启动一个“默认”事务。因此,为了确保每个会话都有独立的事务管理,我们需要为每个新会话创建一个新的 McoSqlSession 实例。
分配上下文的实例化:每个会话都需要实例化一个“分配上下文”。这一步骤确保了会话有足够的资源来执行数据库操作。
指定隔离级别:在调用 session.database()->beginTransaction() 方法时,需要指定所需的隔离级别。例如,在此示例中,我们指定了 MCO_READ_REPEATABLE 隔离级别。
此外,您还可以在 SQL 语句中使用以下两种语法之一来指定隔离级别:
set default_isolation_level ( read_committed | repeatable_read | serializable )
或
set DefaultIsolationLevel ( ReadCommitted | RepeatableRead | Serializable )
优先读取
此事务管理器在 mcotread 库中实现,当访问模式为“主要读取”时,能显著减少上下文切换次数。但缺点是写事务要等到所有读事务处理完毕后才会执行。