在我的Java webapp中,每个实例都在启动时检查数据库是否通过JDBC连接是最新的.如果数据库不是最新的,它将通过执行SQL脚本来执行更新例程.
我无法控制实例何时启动.因此,我需要确保只有一个实例同时在执行数据库更新.理想情况下,我需要锁定整个数据库,但是根据
http://www.postgresql.org/docs/8.4/static/explicit-locking.html
和
http://wiki.postgresql.org/wiki/Lock_database
PostgreSQL不支持它(我仍在使用8.4版).
我还有什么其他选择?
解决方法:
如果控制所有实例的代码,则可以在数据库中创建一个表,每个启动的实例在该表中查找带有时间戳的记录.让我们称它为“锁定”记录.
如果某个进程发现锁定记录不存在,则它将插入该记录并处理所需的数据.
如果某个进程发现该锁记录确实存在,则可以假定另一个进程已创建该锁记录,并且不执行任何操作,忙于等待或执行任何操作.
通过这种设计,您可以有效地在数据库中创建一个“锁”以与您的进程进行同步.您对其进行了编码,因此所有进程都知道它们必须遵守锁定记录的逻辑.
具有锁定功能的第一个进程完成处理后,应清除锁定记录,以便下次重新启动时行为正确.您还需要考虑由于服务器错误或执行错误而无法清除锁定的情况.通常,如果锁的时间早于n分钟,则可以将其视为“过时的”,因此请将其删除,然后重新创建(或仅对其进行更新).
处理“锁定”记录时,请确保在数据库连接上使用Serializable隔离级别,以确保原子性.
Java代码的Service层可以在调用Data Access层之前采用锁定策略来实施.是否使用Hibernate都无关紧要,因为它只是应用程序逻辑.