乐观并发 之所以得名,是因为它基于一种乐观的假设,即事务之间很少会发生冲突;冲突发生在当前事务读取数据和其他事务更新或删除该数据的时间之间。 这与 悲观并发 或锁定相反,应用程序开发人员认为此类冲突是常见的。
在乐观并发中,一行将保持解锁状态,直到更新或删除该行。 此时,将重新读取该行并对其进行检查,以查看自上次读取以来是否已更改该行。 如果行已更改,更新或删除将失败,必须再次尝试。
若要确定行是否已更改,会根据行的缓存版本检查其新版本。 此检查可以基于行版本,例如 SQL Server 中的时间戳列或行中每列的值。 许多 DBMS 不支持行版本。
数据源或应用程序可以实现乐观并发。 在任一情况下,应用程序都应使用低事务隔离级别,例如 Read Committed;使用更高级别会否定使用乐观并发控制所获得的增加的并发性。
如果数据源实现了乐观并发,则应用程序会将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 子句不唯一标识该行,则语句也可能更新或删除其他行;行版本始终唯一标识行,但行值仅当行包含主键时才唯一标识行。