首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Unlock Notification

代码语言:javascript
复制
int sqlite3_unlock_notify(
  sqlite3 *pBlocked,                          /* Waiting connection */
  void (*xNotify)(void **apArg, int nArg),    /* Callback function to invoke */
  void *pNotifyArg                            /* Argument to pass to xNotify */
);

在共享高速缓存模式下运行时,如果无法获取共享高速缓存或共享高速缓存内的单个表上所需的锁,则数据库操作可能会失败,并显示SQLITE_LOCKED错误。有关共享缓存锁定的说明,请参阅SQLite共享缓存模式。这个API可以用于注册一个回调,SQLite将在当前持有所需锁的连接放弃它时调用该回调。只有在定义了SQLITE_ENABLE_UNLOCK_NOTIFY C预处理程序符号的情况下才编译该库,该API才可用。

Callback Invocation Details

当注册一个unlock-notify回调函数时,应用程序提供一个void *指针,该指针在被调用时传递给回调函数。但是,回调函数的签名允许SQLite将它传递给一个void *上下文指针数组。传递给unlock-notify回调的第一个参数是指向void *指针数组的指针,第二个参数是数组中的条目数。

当阻塞连接事务结束时,可能有多个已注册解锁通知回调的阻塞连接。如果两个或多个这样的阻塞连接指定了相同的回调函数,则不是多次调用回调函数,而是使用捆绑在一起的阻塞连接指定的void *上下文指针集合调用一次数组。这为应用程序提供了一个机会,可以确定与未阻止的数据库连接集相关的任何操作的优先级。

Deadlock Detection

假设注册一个unlock-notify回调后,数据库在采取任何进一步行动(一个合理的假设)之前等待回调被发出,那么使用这个API可能会导致应用程序死锁。例如,如果连接X正在等待连接Y的事务结束,并且类似地连接Y正在等待连接X的事务,则两个连接都不会继续,系统可能无限期地保持死锁。

为了避免这种情况,sqlite3_unlock_notify()执行死锁检测。如果对sqlite3_unlock_notify()的给定调用会使系统处于死锁状态,则返回SQLITE_LOCKED,并且不会注册unlock-notify回调。如果在连接B的事务结束时连接A已经注册了解锁通知回调,并且当连接A的事务结束时连接B本身已经注册了解锁通知回调,则称该系统处于死锁状态。间接死锁也被检测到,所以如果连接B已经在连接C的事务结束时注册了解锁通知回调,那么系统也被认为是死锁的,其中连接C正在连接A上等待。任何数量的间接级别是允许。

The "DROP TABLE" Exception

当对sqlite3_step()的调用返回SQLITE_LOCKED时,调用sqlite3_unlock_notify()几乎总是合适的。然而,有一个例外。当执行“DROP TABLE”或“DROP INDEX”语句时,SQLite将检查是否有任何当前正在执行的SELECT语句属于同一个连接。如果有,则返回SQLITE_LOCKED。在这种情况下,没有“阻塞连接”,因此调用sqlite3_unlock_notify()会立即调用unlock-notify回调。如果应用程序然后重新尝试“DROP TABLE”或“DROP INDEX”查询,则可能导致无限循环。

解决此问题的一种方法是检查由sqlite3_step()调用返回的扩展错误代码。如果存在阻塞连接,则扩展错误代码将设置为SQLITE_LOCKED_SHAREDCACHE。否则,在特殊的“DROP TABLE / INDEX”情况下,扩展错误代码只是SQLITE_LOCKED。

代码语言:txt
复制
 SQLite is in the Public Domain.

扫码关注腾讯云开发者

领取腾讯云代金券