数据库 select 语句的并发问题
Concurrency issue on a database select statement
我有一个问题,我正在考虑使用数据库 isolationtype == Serializable 来解决这种情况,但是在阅读了一堆文章之后,我仍然不相信这是解决我下面问题的方法。
设置:
Weblogic cluster > 2 servers
Simple Java JDBC
Servlets, EJB Session beans 2.0
我有一个 table 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 中挑选一个匹配的行并保存另一个 table LAN_Assignment
LAN_Assignment
lan_id | lan_assg_id | some other columns
-------------------------------------------
当 运行 一个 select 语句时,我从 LAN table 得到匹配的行并将其分配给 lan_assignment table。
现在如果有 5 个请求来自客户端(可以是集群中的任何服务器),它们都会选择第一个可用的 LAN 并将其保存到另一个 table。
如何确保选择 LAN 的第一个请求没有被客户端的第二个请求select编辑?
PS:select 语句和业务逻辑并不像这里解释的那样直接。有很多条件选择局域网,保存到Lan_assignment等,
谢谢
Serializable 隔离不是您问题的解决方案(但请留在那里!)
您有几个备选方案来处理这 5 个并发请求(根据您的情况)。一种是让其中 4 笔交易失败,只有 1 笔交易成功。您可以使用唯一约束或使用乐观锁定来执行此操作,并重试因此而失败的操作(但请记住在重试几次后失败)。
或者,你可以使用行锁,如果体积不是很大,这种方法应该可以。
当会话 1 锁定该行时,您可以将 SKIP LOCKED 用于 purpose.With,会话 2 可以跳过它并处理下一个。我相信它也存在于 10g 中,但从未记录在案。
Oracle 10g 有未记录的 SKIP LOCKED 可用于更新,我将其用作解决方案(请参阅下面的选项 3)。
我如何通过其他选项来处理这种情况。
Option 1:
下面的选项将只锁定行,直到事务完成。所有其他事务将继续等待第一个事务释放锁。这有点冒险,因为交易可能会等待很长时间并可能导致死锁。
select .. where .. for update
Option 2:
(Nowait) 如果行被其他一些事务锁定,这将不会等待。它会 return oracle 错误。我可能会捕获异常等待 10 秒,然后再尝试 4-5 次尝试,然后再向用户显示错误。
select .. where... for update nowait
选项 3:(跳过锁定)这将跳过被其他事务锁定的行,这对我有用,因为我不想使用那些被其他事务锁定的行。
select...where ... for update skip locked
我有一个问题,我正在考虑使用数据库 isolationtype == Serializable 来解决这种情况,但是在阅读了一堆文章之后,我仍然不相信这是解决我下面问题的方法。
设置:
Weblogic cluster > 2 servers
Simple Java JDBC
Servlets, EJB Session beans 2.0
我有一个 table 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 中挑选一个匹配的行并保存另一个 table LAN_Assignment
LAN_Assignment
lan_id | lan_assg_id | some other columns
-------------------------------------------
当 运行 一个 select 语句时,我从 LAN table 得到匹配的行并将其分配给 lan_assignment table。
现在如果有 5 个请求来自客户端(可以是集群中的任何服务器),它们都会选择第一个可用的 LAN 并将其保存到另一个 table。
如何确保选择 LAN 的第一个请求没有被客户端的第二个请求select编辑?
PS:select 语句和业务逻辑并不像这里解释的那样直接。有很多条件选择局域网,保存到Lan_assignment等,
谢谢
Serializable 隔离不是您问题的解决方案(但请留在那里!)
您有几个备选方案来处理这 5 个并发请求(根据您的情况)。一种是让其中 4 笔交易失败,只有 1 笔交易成功。您可以使用唯一约束或使用乐观锁定来执行此操作,并重试因此而失败的操作(但请记住在重试几次后失败)。
或者,你可以使用行锁,如果体积不是很大,这种方法应该可以。
当会话 1 锁定该行时,您可以将 SKIP LOCKED 用于 purpose.With,会话 2 可以跳过它并处理下一个。我相信它也存在于 10g 中,但从未记录在案。
Oracle 10g 有未记录的 SKIP LOCKED 可用于更新,我将其用作解决方案(请参阅下面的选项 3)。
我如何通过其他选项来处理这种情况。
Option 1:
下面的选项将只锁定行,直到事务完成。所有其他事务将继续等待第一个事务释放锁。这有点冒险,因为交易可能会等待很长时间并可能导致死锁。
select .. where .. for update
Option 2:
(Nowait) 如果行被其他一些事务锁定,这将不会等待。它会 return oracle 错误。我可能会捕获异常等待 10 秒,然后再尝试 4-5 次尝试,然后再向用户显示错误。
select .. where... for update nowait
选项 3:(跳过锁定)这将跳过被其他事务锁定的行,这对我有用,因为我不想使用那些被其他事务锁定的行。
select...where ... for update skip locked