【问题标题】:Is it possible to lock a database table record indefinitely via JDBC/hibernate?是否可以通过 JDBC/hibernate 无限期地锁定数据库表记录?
【发布时间】:2015-02-25 18:44:30
【问题描述】:

我正在开发一个 Java Web 应用程序,该应用程序涉及为每个用户分配某些资源。

资源在用户登录时由服务器分配给用户,并在用户注销/会话超时时回收。

网络上有多个服务器实例,它们之间不能同时共享同一个资源。因此,一旦资源被分配给用户,它就为该用户独占,直到服务器回收它或停止运行。因此,服务器端必须能够检查资源的可用性,并在它崩溃时释放它(否则无法通过其他服务器实例重新分配资源)。

我的计划是将资源定义存储在数据库表中,每条记录代表一个这样的资源,一旦资源分配给用户,每个服务器都会读取并锁定记录,这样就没有其他服务器了实例可以在使用时重新分配它,服务器故障会释放锁并使资源可用。

问题是这个记录级锁必须无限期地保持活动状态,即只要用户保持在线,锁就会在那里通知其他服务器资源已被分配。

所以我想知道是否可以使用 JDBC 或休眠应用这种锁?如果不可能,有没有什么替代方案可以在不加锁的情况下达到同样的效果?

【问题讨论】:

  • 表和/或行锁定取决于数据库引擎,而不是 JDBC。 JDBC 也可以这样做,具体取决于您为连接设置的事务级别。
  • 听起来是个糟糕的设计,我无法扩展。
  • @duffymo 可扩展性在这里不是问题。此网页应用仅供内部使用,用户总数不超过数百人。

标签: java hibernate jdbc locking


【解决方案1】:

不,数据库锁不适用于这种用途。锁是事务的一部分,事务应该很短。

您可以使用额外的“资源使用情况”表来管理资源的状态。它可以有一个与资源定义 ID、“正在使用”标志、用户 ID、服务器 ID 和上次使用资源的时间相关的列。

服务器可以通过在“资源使用”表中插入或更新一行并将“使用中”标志设置为 true(这需要在一个短事务中完成)来为用户声明资源。如果两个服务器/事务要求相同的资源,则一个事务将失败(或更新将导致更新 0 行)。捕获此故障并为另一个无人认领的资源重复这些操作。

当服务器启动时,它需要检查任何已声明的资源并取消声明它们(例如,如果服务器被杀死并重新启动)。如果一台服务器崩溃,另一台服务器将不得不取消对崩溃服务器声称的资源的认领。这意味着服务器以某种方式了解彼此的健康状况(在线/离线)。一种方法是有一个带有“资源服务器”的单独表,其中每个服务器定期更新特定于服务器的行中的时间戳:如果有一段时间没有更新时间戳,另一个健康的服务器可以决定取消从已离线的服务器。请注意:这很难做到正确(例如,如果数据库离线一段时间,服务器必须在数据库再次在线后等待额外的一段时间才能查找离线服务器)。也许您可以找到“资源服务器”表的替代方案,它使用某种集群技术来为您解决这个问题。

最后,每个服务器中的清扫器服务需要查看“使用中”资源的“最后使用”时间戳。清扫器服务应该没有什么要报告的,但如果会话丢失或清理代码无法正常运行,清扫器服务至少会通知您存在资源泄漏。

【讨论】:

    猜你喜欢
    • 2014-09-20
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 2018-08-21
    • 1970-01-01
    相关资源
    最近更新 更多