开放式并发
乐观并发从乐观假设中派生出其名称,该假设任务事务之间的冲突很少发生;据说,当另一个事务在当前事务读取数据的时间与更新或删除数据的时间之间更新或删除一行数据时,会发生冲突。 这与悲观并发或锁定相反,在悲观并发或锁定中,应用程序开发人员认为此类冲突是常见的。
在乐观并发中,在更新或删除行的时间到来之前,行将保持解锁状态。 此时,将重新读取该行并对其进行检查,以查看该行自上次读取以来是否已更改。 如果行已更改,更新或删除将失败,必须再次尝试。
要确定行是否已更改,根据行的缓存版本检查其新版本。 此检查可以基于行版本,例如 SQL Server 中的时间戳列或行中每列的值。 许多 DBMS 不支持行版本。
数据源或应用程序可以实现乐观并发。 在任一情况下,应用程序都应使用低事务隔离级别,例如“读取已提交的内容”;使用更高级别会否定使用乐观并发获得增加的并发性。
如果数据源实现了乐观并发,则应用程序会将 SQL_ATTR_CONCURRENCY 语句属性设置为 SQL_CONCUR_ROWVER 或 SQL_CONCUR_VALUES。 要更新或删除行,它会执行定位更新或删除语句或调用 SQLSetPos,就像使用悲观并发一样;如果更新或删除因冲突而失败,驱动程序或数据源将返回 SQLSTATE 01001(游标操作冲突)。
如果应用程序本身实现乐观并发,则会将 SQL_ATTR_CONCURRENCY 语句属性设置为 SQL_CONCUR_READ_ONLY 来读取行。 如果它将比较行版本,并且不知道行版本列,则会使用 SQL_ROWVER 选项调用 SQLSpecialColumns 来确定此列的名称。
应用程序通过增加对 SQL_CONCUR_LOCK 的并发性(获取对行的写入访问权限)以及使用 WHERE 子句(该子句指定应用程序读取该行时所具有的版本或值)执行 UPDATE 或 DELETE 语句来更新或删除该行。 如果此后该行已更改,则该语句将失败。 如果 WHERE 子句不唯一标识行,则语句也可能更新或删除其他行;行版本始终唯一地标识行,但仅当行值包含主键时才唯一标识行。