使用ODBC显式锁定和解除锁定表格

3

我需要在MSSQL Server数据库中执行一些数据计算,然后将结果保存在同一数据库中。

我需要将表的(部分)数据加载到C++数据结构中,执行一个可能需要相当长时间的计算,最后向同一表中添加一些行。

问题在于,多个用户可以同时访问数据库,并且由于数据加载到内存中直到计算结果写入表格,因此我希望锁定该表格。

使用ODBC SDK,是否可以显式锁定和解锁表的一部分?

我尝试了以下测试程序,但不幸的是,在StmtHandle1被释放之前,INSERT语句成功执行:

SQLDriverConnect(ConHandle1,  NULL, (SQLCHAR *)"DRIVER={ODBC Driver 13 for SQL Server};"
                                               "SERVER=MyServer;"
                                               "DATABASE=MyDatabase;"/*, ... */);

SQLSetStmtAttr(StmtHandle1,SQL_ATTR_CONCURRENCY,(SQLPOINTER)SQL_CONCUR_LOCK,SQL_IS_INTEGER);

SQLExecDirect(StmtHandle1, (SQLCHAR *)"SELECT * FROM [MyTable] WITH (TABLOCKX, HOLDLOCK)", SQL_NTS);


SQLDriverConnect(ConHandle2, NULL, (SQLCHAR *)"DRIVER={ODBC Driver 13 for SQL Server};"
                                              "SERVER=MyServer;"
                                              "DATABASE=MyDatabase;"/*, ... */);

SQLSetStmtAttr(StmtHandle2,SQL_ATTR_CONCURRENCY,(SQLPOINTER)SQL_CONCUR_LOCK,SQL_IS_INTEGER);

SQLExecDirect(StmtHandle2, (SQLCHAR *)"INSERT INTO [MyTable] VALUES (...)", SQL_NTS);
1个回答

2

很遗憾,在释放 StmtHandle1 前,INSERT 语句已经成功执行。

默认情况下,SQL Server 操作处于自动提交模式,即为您打开事务并提交它。

您请求 TABLOCKX 并且该表在您的事务期间被锁定,但您实际需要的是显式地打开一个事务并在完成计算之前不要 commit/rollback 它,即应使用

begin tran; SELECT top 1 * FROM [MyTable] WITH (TABLOCKX, HOLDLOCK);

你不需要阅读整个表格,top 1 * 就足够了。


{btsdaf} - metalfox
{btsdaf} - sepupic
好的,它运行得很好。我必须为当前连接设置自动提交模式为关闭:SQLSetConnectAttr(ConHandle, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, NULL);,然后使用SQLEndTran(SQL_HANDLE_DBC, ConHandle, SQL_COMMIT);提交事务。 - metalfox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接