【问题标题】:Getting Older timestamp from query从查询中获取较旧的时间戳
【发布时间】:2018-06-18 06:11:14
【问题描述】:

以下是我使用选择查询获取当前数据库时间的方法。

public Date getDBDateTime() { 
    Session session = sessionFactory.getCurrentSession();   
    return (Date) session.createSQLQuery("select now() as date").uniqueResult();    
}

此方法从数据库返回当前时间戳,但有时此方法会从数据库返回较旧的时间戳。 (有时 30 到 1 分钟)

这是我在spring中调用dao方法的服务层方法。

@Transactional
public void doSomething(){
   Date now  = dao.getDBDateTime();
   //service specific logic
}

需要为某些事件计时计算选择数据库时间,并将数据库和应用服务器从同一时区解耦。

谁能指出我哪里出了问题并提出解决建议?

感谢期待!

【问题讨论】:

  • 你的数据库和应用程序在不同的服务器/时区吗?
  • @AlpeshJikadra 目前他们在不同的服务器上,但时区相同。
  • 很难重现您的问题,我建议以字符串格式获取日期并使用 Java 将该字符串转换为 LocalDateTime
  • getDBDateTime() 是否返回java.util.Date?还是其他Date
  • @RoshanaPitigala 不,它不是 java.util.Date 但它返回 java.sql.Timestamp

标签: java spring postgresql hibernate postgresql-9.4


【解决方案1】:

now() 不返回挂墙时间,而是返回交易开始时的当前时间戳。在一个事务中重复调用now() 将始终返回相同的值。请参阅the documentation 了解更多信息。

所以我怀疑如果now() 返回一个旧时间,您有一个长时间运行的未处理事务。这是一个应用程序错误,因为长时间运行的事务将使VACUUM 无法正常工作,并且还会长时间锁定对象。

要获取当前的挂钟时间,请使用函数clock_timestamp()

【讨论】:

  • 感谢您的回答,但在我的应用程序中,服务层代码由一个控制器调用,该控制器是一个休息 api,并以毫秒为单位返回。那么怎么会有一个长期运行的事务呢?我的意思是,如果我在下午 2 点触发 api 并且需要 1 秒来返回响应,那么 30s-1m 的旧时间戳也不符合这种逻辑。我错过了什么吗?
  • 我不知道您的设置,但您可以使用SELECT xact_start FROM pg_stat_activity WHERE pid = pg_backend_pid(); 了解您当前交易的开始时间。
  • 感谢使用 clock_timestamp() 实际上解决了这个问题,但我仍然无法弄清楚长时间运行事务背后的原因。我曾经从 sessionfactory 收到的 session 中思考,每次为每个 rest 调用提供一个新事务。你能建议我一些进一步的参考/阅读来解决这个问题吗?
  • 我对Hibernate一无所知,但我认为它要么是那里的错误,要么是你使用它的方式。对不起,如果我不能进一步帮助你。在 PostgreSQL 中设置 log_statement = 'all' 并检查 Hibernate 的真正作用可能很有用。也许这会给你一个线索。
猜你喜欢
  • 2019-02-26
  • 2020-08-18
  • 2019-03-05
  • 2013-06-26
  • 1970-01-01
  • 2012-05-20
  • 1970-01-01
  • 2015-08-24
  • 1970-01-01
相关资源
最近更新 更多