简体   繁体   English

Hibernate 启动很慢

[英]Hibernate startup very slow

For some reason, the startup of my hibernate application is unbarrably slow.出于某种原因,我的休眠应用程序的启动速度非常慢。 (up to 2 min) I have been thinking that the c3p0 configuration is plain wrong ( related question ) but studying the logs shows, that there is no activity just after the connection to the server is established. (最多 2 分钟)我一直认为 c3p0 配置完全错误( 相关问题),但研究日志显示,在与服务器的连接建立后没有任何活动。 Also, using the built-in polling capabilities of Hibernate shows the same result.此外,使用 Hibernate 的内置轮询功能显示相同的结果。

Here is a snippet from the logs:这是日志中的一个片段:

20:06:51,248 DEBUG BasicResourcePool:422 - decremented pending_acquires: 0
20:06:51,248 DEBUG BasicResourcePool:1644 - trace com.mchange.v2.resourcepool.BasicResourcePool@1acaf0ed [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@5f873eb2)
20:06:51,248 DEBUG BasicResourcePool:1644 - trace com.mchange.v2.resourcepool.BasicResourcePool@1acaf0ed [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@5f873eb2)
20:06:51,273 DEBUG JdbcServicesImpl:121 - Database ->
       name : PostgreSQL
    version : 9.1.6
      major : 9
      minor : 1
20:06:51,274 DEBUG JdbcServicesImpl:127 - Driver ->
       name : PostgreSQL Native Driver
    version : PostgreSQL 9.2 JDBC4 (build 1002)
      major : 9
      minor : 2
20:06:51,274 DEBUG JdbcServicesImpl:133 - JDBC version : 4.0 ##### HANGS FOR 2 MINUTES  ON THIS LINE #####
20:08:14,727  INFO Dialect:123 - HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
20:08:14,736  INFO LobCreatorBuilder:120 - HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException
20:08:14,736 DEBUG GooGooStatementCache:297 - checkinAll(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0
20:08:14,736 DEBUG GooGooStatementCache:297 - checkinAll(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0
20:08:14,883 DEBUG BasicResourcePool:1644 - trace com.mchange.v2.resourcepool.BasicResourcePool@1acaf0ed [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@5f873eb2)
20:08:14,883 DEBUG BasicResourcePool:1644 - trace com.mchange.v2.resourcepool.BasicResourcePool@1acaf0ed [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@5f873eb2)
20:08:14,883 DEBUG GooGooStatementCache:297 - checkinAll(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0

(Please mind the #comment#.) (请注意#comment#。)

I also tried an older Postgres JDBC Driver with no luck whatsoever.我还尝试了一个旧的 Postgres JDBC 驱动程序,但没有任何运气。

Connecting to a local Database works just fine.连接到本地数据库工作正常。 Connection is established immediately and I can query the database.连接立即建立,我可以查询数据库。 This remote db is a Heroku dev instance.这个远程数据库是一个 Heroku 开发实例。 I tried it with another remote as well.我也用另一个遥控器试过。 Same outcome.结果一样。

I'm out of ideas what I can check now to get rid of this annoyance.我不知道我现在可以检查什么来摆脱这种烦恼。 Any help would be much appreciated.任何帮助将非常感激。

Maybe my hibernate.cfg.xml is helpful:也许我的 hibernate.cfg.xml 有帮助:

http://www.hibernate.org/dtd/hibernate- http://www.hibernate.org/dtd/hibernate-

configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="connection.driver_class">org.postgresql.Driver</property>
        <property name="connection.url"/>
        <property name="connection.default_schema"/>
        <property name="connection.username"/>
        <property name="connection.password"/> 

        <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
            <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
        <property name="current_session_context_class">thread</property>            
        <property name="hibernate.c3p0.acquire_increment">3</property>
        <property name="hibernate.c3p0.min_size">3</property>
        <property name="hibernate.c3p0.max_size">10</property>
        <property name="hibernate.c3p0.timeout">300</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>
        <property name="hibernate.c3p0.acquireRetryDelay">500</property>

        <property name="show_sql">true</property>
        <property name="format_sql">false</property>

        <property name="hbm2ddl.auto">validate</property>

        <mapping class="core.entities.Exam" />
        <mapping class="core.entities.Examination" />
        ...
    </session-factory>
</hibernate-configuration>

EDIT: I tried to find the reason for the delay via logs and profiling but have been widely unsuccessful with it.编辑:我试图通过日志和分析找到延迟的原因,但一直没有成功。 (I'm not that advanced in this area though.) In the end I did go with try and fail and changed my db for a remote MySQL instance to check if any difference occurs. (不过,我在这方面并不是那么先进。)最后,我确实尝试并失败了,并更改了远程 MySQL 实例的数据库以检查是否发生任何差异。 Turns out, that the connection is established nearly immediately.事实证明,连接几乎立即建立。

See Hibernate Slow to Acquire Postgres Connection参见Hibernate 缓慢获取 Postgres 连接

hibernate.temp.use_jdbc_metadata_defaults=false

To avoid meta-data reload during SessionFactory creation.避免在 SessionFactory 创建期间重新加载元数据。

For Postgres, add in application config:对于 Postgres,添加应用程序配置:

spring.jpa.database-platform = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false

First line is necessary if not determine Dialect如果没有确定方言,第一行是必要的

Results结果

Before:前:

09:10:19.637 [main] INFO  o.h.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
09:14:17.159 [main] INFO  org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.PostgreSQL9Dialect

~4 minutes ~4 分钟

After:后:

09:40:10.930 [main] INFO  o.h.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
09:40:11.043 [main] INFO  org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect

~1 minute ~1 分钟

Startup slow may be caused by this config:此配置可能导致启动缓慢:

<property name="hbm2ddl.auto">update</property>

This config means when hibernate start, check if the entity matching with ddl, and do action such as 'create','update'.这个配置意味着在hibernate开始时,检查实体是否与ddl匹配,并做'create','update'等动作。 This will cost too much time.这将花费太多时间。

So the solution is comment this config.所以解决方案是评论这个配置。 Then hibernate will start without validate.然后休眠将在没有验证的情况下启动。

If it is abnormally slow then you probably have a lock in your application, or some resource blocks.如果它异常缓慢,那么您的应用程序可能被锁定,或者某些资源块。 In any case download VisualVM (JDK includes jconsole, dumbed down version of it) and check what your threads are doing, where they are stuck (threaddump) and if that doesn't give any quick answers, turn on the profiler.在任何情况下都下载 VisualVM(JDK 包括 jconsole,它的简化版本)并检查您的线程正在做什么,它们被卡在何处(线程转储),如果这没有给出任何快速答案,请打开分析器。

The issue occured for me when I updated my database from 10g to 11. I found following setting in the code:当我将数据库从 10g 更新到 11 时,出现了这个问题。我在代码中发现了以下设置:

    hibernateProperties.setProperty("hibernate.dialect","org.hibernate.dialect.Oracle10gDialect");

and had to change the dialect as follows:并且不得不改变方言如下:

    hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle11gDialect");

At one point this no longer worked for me and I had to change the following to be not stuck at the "HHH000400: Using dialect: org.hibernate.dialect.Oracle10gDialect":一度这对我不再有效,我不得不更改以下内容以免卡在“HHH000400:使用方言:org.hibernate.dialect.Oracle10gDialect”:

hibernateProperties.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false");

Additionally I had to comment out the following to be not stuck at "HV000001: Hibernate Validator 6.1.5.Final":此外,我必须注释掉以下内容,以免停留在“HV000001:Hibernate Validator 6.1.5.Final”:

        // hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "validate");

What container are you using?你用的是什么容器? c3p0 should be installed in the container, eg Tomcat. c3p0 应该安装在容器中,例如 Tomcat。 If you are running unit tests, for chrissakes, don't use a connection pool.如果您正在运行单元测试,请不要使用连接池。 If you put it into tomcat, you do that with a Resource tag and then connect to it using JNDI.如果将其放入 tomcat,则使用 Resource 标记执行此操作,然后使用 JNDI 连接到它。 Best way to do it.最好的方法来做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM