乐观并发策略通过消除读取和更新操作之间数据库中的所有锁定解决了性能问题,同时还提供了检测更新丢失的机制。和数据库并发一样,乐观并发给每个事务一个自己的bean实例,但是它没有在事务进行过程中在EJB容器或数据库中包含任何锁。对于进行读锁定的数据库(非Oracle数据库),容器在一个单独的事务(该事务在数据读取操作一完成就立即进行)中读取bean数据,从而避免了读取锁,并且提供了更高的可伸缩性。
这种更新丢失检测机制并不新鲜,在Java创建之前就已经存在好长时间了。该模式的基本思想简单而强大:在更新时,首先进行检查,以确定表中的数据在被第一个进程读取之后是否被其他进程修改。实际中,这通常是通过在update语句的where子句中包含一个或多个额外的“版本”列来实现的。下面给出了一个简单的SQL的例子,其中version列是一个数值,在每次更新操作之后会递增:
-- at Entity load time"container executes select of bean fields,
在进行更新时,容器通过执行以下代码能检测出数据库中实际上有多少行被更新:
如您所见,该方法可使服务器避免更新丢失问题,并且不需要在容器或数据库中进行长期的锁定。该策略尤其适用于数据库中读取次数远多于更新次数,因此更新碰撞的几率很小时。通常,对于大部分应用程序来说是这样的。
一个用数字表示的版本列不是在WebLogic Server中实现乐观并发策略的唯一途径。相反可以使用一个时间戳列。(注意,数据库应该允许您存放足够精确的时间戳值)。时间戳的使用给您带来了额外好处,那就是知道记录的最后一次更新是什么时候。有时候在使用遗留数据库模式时,会不愿意或不可能更改数据表以添加一个版本列。这种情况下,WebLogic Server可以检查表中事务期间被读取的所有列(实体bean中的所有字段),或者只检查被当前事务更新的列。乐观并发可用于遗留模式,无需对数据表进行任何修改,但是开销略微增加(意味着更复杂的SQL更新)。