我对Oracle中锁定的主题感到困惑。就我的研究引导我而言,您可以使用FOR UPDATE NOWAIT/WAIT
锁定行。
我想以这种方式实现我的锁定。一旦我发出FOR UPDATE
,该行就会被锁定,我可以检查是否有突变。我有一个versionNumber列,每次更新表时都会增加1。我可以使用此versionNumber来验证行是否已突变?
if (:new.versionNum != :old.versionNum)
raise_application_error(20000, 'Mutated');
end if;
我的问题是我在哪里开始编写代码行FOR UPDATE
?我做了一个小GUI来处理更改名字并将它们保存回数据库。这是在oracle上的那个表上还是在JDBC客户端的一个触发器中完成的?
任何澄清都会很好!
由于
答案 0 :(得分:2)
锁定有两种常用方法。
首先,你有悲观的锁定。在此方法中,您锁定行(SELECT ... FOR UPDATE
),以防止其他人更改行。然后你做UPDATE
。提交更改时,将释放锁定。在这种情况下,不需要具有版本号/时间戳列(至少不支持锁定),并且代码相对容易。
悲观锁定的缺点是,您需要在用户坐在可能编辑数据的页面上时保持锁定。如果您正在构建基于Web的应用程序,那么这在技术上确实很难,因为HTTP是无状态协议。最初呈现页面的请求通常会从连接池获得连接,执行SELECT
,然后在页面完成后将连接返回到池。后续更新数据的请求通常发生在具有不同数据库会话的不同连接上,因此您无法在第一个会话中锁定行并在第二个会话中更新它。如果您想悲观地锁定该行,则需要在后端执行大量工作,以确保将一个数据库连接绑定到特定的中间层会话,直到用户完成编辑数据为止。这通常会对可伸缩性产生非常不利的影响并引入各种会话管理问题 - 例如,您如何知道我是否请求了页面,锁定了一行,然后关闭了我的浏览器而没有注销或进行更改?您要将记录锁定在数据库中多长时间?如果某个其他会话试图锁定该行会发生什么?如果第一个人出去吃午饭,你会让这个会话阻止等待锁多长时间?通常,人们不会在基于Web的应用程序中实现悲观锁定,因为管理会话和会话状态实在太不切实际。
第二个选项是乐观锁定。在此方法中,您将向行添加版本号/时间戳。在查询数据时选择此版本号/时间戳。然后,在稍后进行更新时,在WHERE
子句中使用它,并检查实际修改的行数。如果您只修改了一行,则表示您在读取该行后没有更改该行。如果修改0行,则表示该行确实已更改,您可以处理错误。
因此,例如,您将选择数据以及版本号
SELECT address_line1, city, state, zip, version
FROM addressTable
WHERE address_id = `<<some key>>`
当您准备好进行更新时,您会执行以下操作:使用version
中的UPDATE
并在行更改时抛出错误
UPDATE addressTable
SET address_line1 = `<<new address line 1>>`,
city = `<<new city>>`,
state = `<<new state>>`,
zip = `<<new zip>>`,
version = version + 1
WHERE address_id = `<<some key>>`
AND version = `<<version you read initially>>`
IF( SQL%ROWCOUNT = 0 )
THEN
-- Darn. The row must have changed since you read it. Do something to
-- alert the user. Most likely, the application will need to re-query the
-- data to see what the address has been changed to and then ask the user
-- whether they want to re-apply the changes.
RAISE_APPLICATION_ERROR( -20001, 'Oops, the row has changed since you read it.' );
END IF;
然后,您的应用程序将对错误执行一些有用的操作。通常,这意味着要做一些事情,比如再次查询数据,向用户显示更改,并询问他们是否仍然想要应用他们的更改。例如,如果我读了一个地址并开始编辑它,去吃午餐,我的同事登录,读取相同的地址,进行一些编辑并保存,然后我返回并尝试保存我的更改,这通常是有道理的向我展示一些事情,告诉我我的同事已经将地址更改为新的内容 - 我是否要继续进行编辑,或者我是否要放弃它们。