我遇到了一个问题,我正在考虑使用数据库隔离类型==Serializable来解决这种情况,但在阅读了大量文章后,我仍然不相信这是我下面问题的解决方案。
设置:
Weblogic cluster > 2 servers
Simple Java JDBC
Servlets, EJB Session beans 2.0
我有一个表LAN
,我们根据客户端提供的输入来选择匹配的值。
局域网
lan_id | name | some_values | is_available
-------------------------------------
13 | ss | 3234 | yes
12 | sssd| 3234 | yes
14 | sssd| 3234 | yes
15 | ssaa| 3234 | yes
现在,在业务逻辑中,我需要从LAN中选择一个匹配的行,并保存另一个表LAN_Assignment
LAN_Assignment
lan_id | lan_assg_id | some other columns
-------------------------------------------
当运行select语句时,我从LAN表中获得一个匹配的行,并将其分配给LAN_assignment表。
现在,如果有5个请求来自客户端(可以是集群中的任何服务器),它们都会选择第一个可用的LAN并将其保存到另一个表中。
如何确保从客户端发出的第二个请求没有选择第一个获取LAN的请求?
附言:select语句和业务逻辑并不像这里解释的那样直截了当。有很多条件可以选择LAN并将其保存到LAN_assignment等,
感谢
您可以使用SKIP LOCKED。当会话1锁定该行时,会话2可以跳过该行并处理下一行。我相信它在10g中也存在,但从未记录在案。
Serializable隔离不是解决您的问题的方法(但请将其留在那里!)
您有几个备选方案来处理这5个并发请求(根据您的场景)。一种是其中4个交易失败,只有1个会成功。您可以使用唯一约束或乐观锁定来执行此操作,并重试因此而失败的操作(但请记住,重试几次后会失败)。
或者,您可以使用行锁,如果卷不是很大,这种方法应该可以很好地工作。
Oracle 10g有未记录的SKIP LOCKED可供更新,我将其用作解决方案(请参阅下面的选项3)。
我经历过如何处理这种情况的其他选择。
Option 1:
下面的选项只会锁定行,直到事务完成。所有其他事务将继续等待第一个事务释放锁。这有点风险,因为事务可能会等待很长时间,并可能导致死锁。
select .. where .. for update
Option 2:
(Nowait)如果行被其他事务锁定,则不会等待。它将返回oracle错误。我可能会发现异常,等待10秒,然后再尝试4-5次,然后向用户显示错误。
select .. where... for update nowait
选项3:(跳过锁定)这将跳过被其他事务锁定的行,这对我来说是有用的,因为我不想使用那些被其他事务锁住的行。
select...where ... for update skip locked