乐观并发控制(optimistic concurrency control, OCC)
乐观并发是一个应用于事务系统(eg,关系型数据库管理系统与软件内存事务)的并发控制方法。
OCC假设大多数的事务可以在不互相干扰的情况下完成。
当事务运行时,事务不需要申请资源的锁,便可以使用这些资源。
在提交之前,每一个事务都会验证没有其他的事务修改了它所读取的数据。
如果检测显式存在冲突修改,提交事务将被回卷并重新开始执行。
OCC通常用于低数据争夺的环境下。当冲突较少时,事务的完成将会没有管理锁的消耗,并且不需要令事务等待其他的事务锁释放,其结果导致比其他的并发控制方法有着更高的吞吐量。
然而,如果数据资源争夺较为频繁,反复重启事务的花费将会极大地伤害性能,通常认为在这种情况下,其他并发控制方法拥有更好的性能。
但是,基于锁(悲观)的方法也可能造成糟糕的性能,因为即使死锁被避免,锁也会极大地限制有效的并发。
OCC阶段
更具体地说,OCC事务涉及以下阶段:
开始:记录事务开始的时间戳。
修改:读取数据库值,暂时写变化。
验证:检查其他的事务是否修改了当前事务使用的数据。这包括在当前事务开始时间之后完成的事务,可能包括在验证期间仍保持活跃的事务。
提交/回卷:如果没有冲突,所有的改变生效。如果产生了冲突,解决它,通常是终止事务,尽管其他解决方法仍然可能。必须注意避免TOCTTOU bug,特别是,如果此阶段与之前的阶段并不是作为单个原子操作执行。
Web用法
HTTP的无状态特性使得对于web用户接口锁机制不可行。
用户开始编辑一条记录,然后在不遵守取消或注销链接的情况下离开是比较常见的。
如果锁机制被应用,其他试图编辑相同记录的用户必须等待第一个用户的锁超时。
HTTP提供了一个内置OCC形式:
GET方法对于一个资源返回一个ETag,随后的PUT方法在If-Match头部中使用这个ETag值。
当一个PUT成功,第二个将会失败,因为If-Match中的值基于当前资源的第一个版本。
一些数据库管理系统在本地提供了OCC,从而不需要特定的应用代码。
其他的一些数据库,应用可以在数据库之外实现OCC层,用于避免等待或默默重写记录。
在这种情况下,表达将包括一个隐藏字段,内含记录原始内容,时间戳,序列号或一个不透明令牌。
在提交之后,这将与数据库进行比较。如果不同,冲突解决将会被调用。