java–Hibernate PostgreSQL:使用独占锁延迟加载

java–Hibernate PostgreSQL:使用独占锁延迟加载,第1张

概述在这一天上,我的头发被撕掉了几天.我们在使用独占数据库锁时遇到了一些问题,导致我们的生产系统出现性能问题一段时间了.我能够仔细研究它,并注意到持有独占锁的查询是由Hibernate的延迟加载生成的选择.我们使用Spring事务管理,在服务入口点定义@Transactional(readOnly =“true”).我们使用会话每请求模型和映射到传输对象的实体.

在这一天上,我的头发被撕掉了几天.我们在使用独占数据库锁时遇到了一些问题,导致我们的生产系统出现性能问题一段时间了.我能够仔细研究它,并注意到持有独占锁的查询是由Hibernate的延迟加载生成的选择.

我们使用Spring事务管理,在服务入口点定义@Transactional(Readonly =“true”).我们使用会话每请求模型和映射到传输对象的实体.读取数据库默认隔离级别已提交. JDBC驱动程序配置为read committed.我使用以下方法检查了实际交易的隔离级别:

select current_setting('transaction_isolation')

哪个返回read committed.我们使用JPA来配置Hibernate映射.我们没有在任何地方明确升级交易.在这个特定的事务中,我们只运行select语句.打开Hibernate sql日志记录我没有看到任何这些:

select ... for update

只记录简单的select语句.

这似乎是两件事之一.我对read committed的理解是完全关闭的,读取提交的隔离级别应该导致在执行选择的事务期间保持独占的行级锁定.或者正在发生其他事情并错误地升级事务所持有的锁.

任何帮助,将不胜感激.

编辑1:

好吧,在这一条路上走了很长的路.事实证明这与锁定无关.我用来检测锁的查询已经过时,并且显示锁定类型为“virtualxID”.一些挖掘告诉我们,virtualxID是每个事务自身锁定的锁,因为Postgresql的内部原因与此讨论没有密切关系.我们cron’d另一个监控查询测试真正的独占锁,还没有见过.

这是我们用来监视“virtualxID”锁的查询,这个锁更像是一个长时间运行的查询监视器:

SELECT pg_stat_activity.datname,pg_locks.mode,pg_locks.locktype,pg_locks.granted,pg_stat_activity.usename,pg_stat_activity.query,age(Now(),pg_stat_activity.query_start) AS "age",pg_stat_activity.pIDFROM pg_stat_activity,pg_locksleft OUTER JOIN pg_class ON (pg_locks.relation = pg_class.oID)WHERE  age(Now(),pg_stat_activity.query_start) > interval '1 minute' AND  pg_stat_activity.datname <> 'postgres' AND  pg_locks.pID=pg_stat_activity.pID AND  pg_stat_activity.query not like '%autovacuum%' AND  pg_stat_activity.query not like '%copY%stdout%'  order by query_start;

这是我们得到的一些输出:

一个简单的选择current_timestamp运行超过一个小时!

无论如何,对于那些感兴趣的人,它开始看起来像这些神秘的长时间运行的查询偶尔会耗尽我们的数据库连接池.所以我们提高了连接池的限制,现场网站又恢复了嗡嗡声.我们已经在关键流程上设置了应用程序端超时和重试逻辑,以处理偶尔的打嗝.而这些天我们通常至少有一个数据库线程卡住了这些奇怪的执行查询之一.绝对不理想:(

我们将尝试打开基于成本的自动吸尘器,看看这是否有助于解决问题.

编辑2:

事实证明这是一段漫长的旅程,可能就在它的尽头.为了响应这种行为,除了上面提到的数据库查询监控之外,我们还支持了批处理错误报告.结合一些智能超时,这使我们能够将特定的应用程序用例与长时间运行的数据库查询相关联.这使我们能够对生产中出现的错误做出反应,以防止特定用法挂起JVM节点.

我们还能够解决为什么在一个进程中长时间运行的只读TX会挂起连接到同一数据库的其他进程的问题.这是事情变得有点奇怪的地方.我们使用hibernate-memcached将hibernate的二级缓存移动到连接到同一数据库的所有Java进程的共享memcached服务器.每当我们得到奇怪的挂起行为时,JVM进程中就会有大量的memcached客户端线程.

删除hibernate-memcached模块后,回到ehcache进行二级缓存,我们注意到奇怪的多JVM衰弱的悬挂消失了.我们仍会偶尔收到一封电子邮件,告诉我们TX内部发生的事情比应该发生的要多一些.我们仍然偶尔会出现单个JVM进程,因为它有太多的这些长TX正在大规模进行.但是我们不再看到一个JVM中的进程以某种方式影响其他JVM.以前我们会看到其他节点没有响应,直到我们杀死显示不良TX行为的初始节点.

这没有意义.但后来这个问题从来没有:)

– 蒂姆

最佳答案首先,你需要的是由Jim mlodgenski和Bruce Momjian在JBoss World 2009中提供的出色的Scaling Hibernate Applications和Postgres的演讲,以解决Hibernate和Postgresql最常见的问题(缓存,复制,连接池等).哟可以找到它here:

然后,如果您在延迟加载时遇到问题,可以在纯sql中发送直接查询:

String sql_query = "SELECT insurance_name,ID,invested_amount,avg(i...                 + "invested_amount - avg(invested_amount) OVER(PARTI...                 + "FROM insurance ";query query = session.createsqlquery(sql_query)                    .addScalar("insurance_name",Hibernate.STRING)                    .addScalar("ID",Hibernate.LONG)                    .addScalar("invested_amount",Hibernate.LONG)                    .addScalar("a",Hibernate.DOUBLE)                    .addScalar("diff",Hibernate.DOUBLE);
总结

以上是内存溢出为你收集整理的java – Hibernate PostgreSQL:使用独占锁延迟加载全部内容,希望文章能够帮你解决java – Hibernate PostgreSQL:使用独占锁延迟加载所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1250852.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)