目次
2. 原因分析
が発生します。 3. 解決策
1. MySQL の wait_timeout 属性の値を増やします
" >c3p0 設定ファイルを変更し、Spring 設定ファイルに設定します。
ホームページ データベース mysql チュートリアル MySQL - c3p0 と DBCP 接続プールの使用によって引き起こされる MySql 8 時間の問題に対する詳細なコード解決策

MySQL - c3p0 と DBCP 接続プールの使用によって引き起こされる MySql 8 時間の問題に対する詳細なコード解決策

Mar 09, 2017 am 11:41 AM

この記事では、c3p0 と DBCP 接続プールを使用することによって発生する MySQL 8 時間問題のコード解決策について詳しく説明します。以下に詳細な説明を示します。

1. 問題の説明

私は現在 Java Web プロジェクトに取り組んでいます。フレームワークは Spring MVC+JPA、c3p0 接続プールを使用しています。リリース環境は Tomcat 7 で、プロジェクトは一定期間 (約 1 年間) 実行されます。数時間)、その後にアクセスすると、最初のアクセスではエラーが発生しますが、再び正常にアクセスされ、この問題が複数回発生します。以下はエラーログです:


org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; 
nested exception is javax.persistence.PersistenceException: org.hibernate.TransactionException: JDBC begin transaction failed:   
        at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:428)  
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:372)  
        at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:417)  
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:255)  
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)  
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)  
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)  
        at com.appcarcare.cube.service.UserService
    EnhancerByCGLIB
    a4429cba.getUserDao(<generated>)  
      
        at com.appcarcare.cube.servlet.DataCenterServlet$SqlTimer.connectSql(DataCenterServlet.java:76)  
        at com.appcarcare.cube.servlet.DataCenterServlet$SqlTimer.run(DataCenterServlet.java:70)  
        at java.util.TimerThread.mainLoop(Timer.java:555)  
        at java.util.TimerThread.run(Timer.java:505)  
    Caused by: javax.persistence.PersistenceException: org.hibernate.TransactionException: JDBC begin transaction failed:   
        at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387)  
        at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)  
      
        at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:1397)  
        at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:62)  
        at org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction(DefaultJpaDialect.java:71)  
        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:60)  
        at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:378)  
        ... 11 more  
    Caused by: org.hibernate.TransactionException: JDBC begin transaction failed:   
        at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:76)  
        at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:160)  
      
        at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1426)  
        at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:59)  
        ... 14 more  
    Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure  
      
    The last packet successfully received from the server was 1,836,166 milliseconds ago.  
    The last packet sent successfully to the server was 29,134 milliseconds ago.  
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)  
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)  
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)  
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526)  
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)  
        at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1117)  
        at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3567)  
        at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3456)  
      
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3997)  
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2468)  
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2629)  
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2713)  
        at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:5060)  
        at com.mchange.v2.c3p0.impl.NewProxyConnection.setAutoCommit(NewProxyConnection.java:881)  
        at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:72)  
      
        ... 17 more  
    Caused by: java.net.SocketException: Software caused connection abort: recv failed  
        at java.net.SocketInputStream.socketRead0(Native Method)  
        at java.net.SocketInputStream.read(SocketInputStream.java:150)  
        at java.net.SocketInputStream.read(SocketInputStream.java:121)  
        at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114)  
        at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161)  
        at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189)  
        at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3014)  
        at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3467)  
        ... 25 more
ログイン後にコピー


2. 原因分析

MySQL サーバーのデフォルトの "wait_timeout" は 28800 秒または 8 時間です。これは、接続のアイドル時間が 8 時間を超えることを意味します。 MySQL は接続が自動的に切断されますが、接続プールは接続がまだ有効であると認識します (接続の有効性が検証されていないため)。アプリケーションが接続の使用を申請すると、上記のエラー

が発生します。 3. 解決策

この問題を解決するには 3 つの方法があり、2 番目の方法をお勧めします:

1. MySQL の wait_timeout 属性の値を増やします

mysql インストール ディレクトリ内の設定ファイル my.ini ファイルを変更します (そのようなファイルがない場合は、「my-default .ini」ファイルをコピーして「copy my-default.ini」ファイルを生成し、「copy my-default.ini」ファイルの名前を「my.ini」に変更し、
を設定します。ファイル

wait_timeout=31536000  
interactive_timeout=31536000
ログイン後にコピー
内の

これら 2 つのパラメータのデフォルト値は 8 時間 (60*60*8=28800) です。
注: 1. wait_timeout の最大値は 2147483 (約 24 日) のみです。
2. インターネット上のほとんどの記事で提供されている方法で設定ファイルを変更します。mysql コマンドを使用してこれら 2 つを変更することもできます。属性

2. 接続プール内の接続のライフ サイクルを短縮します

接続プール内の接続のライフ サイクルを短縮し、前に設定した wait_timeout 値より小さくします。アイテム。

c3p0 設定ファイルを変更し、Spring 設定ファイルに設定します。

<bean id="dataSource"  class="com.mchange.v2.c3p0.ComboPooledDataSource">       
    <property name="maxIdleTime"value="1800"/>    
    <!--other properties -->    
</bean>
ログイン後にコピー


3. 接続プール内の接続を定期的に使用します

タイムアウトのためアイドル状態 MySQL が切断されました。
c3p0 設定ファイルを変更し、Spring 設定ファイルに設定します

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">    
    <property name="preferredTestQuery" value="SELECT 1"/>    
    <property name="idleConnectionTestPeriod" value="18000"/>    
    <property name="testConnectionOnCheckout" value="true"/>    
</bean>
ログイン後にコピー



4. 拡張機能

C3P0
C3P0 は、実装を含む lib ディレクトリで Hibernate と一緒にリリースされるオープンソースの JDBC 接続プールです。 jdbc3 および jdbc2 拡張仕様で説明されている Connection および Statement プールの DataSources オブジェクト。 c3p0 設定ファイル

<default-config>   
  <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->   
  <property name="acquireIncrement">3</property>   
  <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->   
  <property name="acquireRetryAttempts">30</property>   
  <!--两次连接中间隔时间,单位毫秒。Default: 1000 -->   
  <property name="acquireRetryDelay">1000</property>   
  <!--连接关闭时默认将所有未提交的操作回滚。Default: false -->   
  <property name="autoCommitOnClose">false</property>   
  <!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么   
  属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试   
  使用。Default: null-->   
  <property name="automaticTestTable">Test</property>   
  <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效   
  保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试   
  获取连接失败后该数据源将申明已断开并永久关闭。Default: false-->   
  <property name="breakAfterAcquireFailure">false</property>   
  <!--当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出   
  SQLException,如设为0则无限期等待。单位毫秒。Default: 0 -->   
  <property name="checkoutTimeout">100</property>   
  <!--通过实现ConnectionTester或QueryConnectionTester的类来测试连接。类名需制定全路径。   
  Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester-->   
  <property name="connectionTesterClassName"></property>   
  <!--指定c3p0 libraries的路径,如果(通常都是这样)在本地即可获得那么无需设置,默认null即可   
  Default: null-->   
  <property name="factoryClassLocation">null</property>   
  <!--Strongly disrecommended. Setting this to true may lead to subtle and bizarre bugs.   
  (文档原文)作者强烈建议不使用的一个属性-->   
  <property name="forceIgnoreUnresolvedTransactions">false</property>   
  <!--每60秒检查所有连接池中的空闲连接。Default: 0 -->   
  <property name="idleConnectionTestPeriod">60</property>   
  <!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->   
  <property name="initialPoolSize">3</property>   
  <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->   
  <property name="maxIdleTime">60</property>   
  <!--连接池中保留的最大连接数。Default: 15 -->   
  <property name="maxPoolSize">15</property>   
  <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements   
  属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。   
  如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->   
  <property name="maxStatements">100</property>   
  <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->   
  <property name="maxStatementsPerConnection"></property>   
  <!--c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能   
  通过多线程实现多个操作同时被执行。Default: 3-->   
  <property name="numHelperThreads">3</property>   
  <!--当用户调用getConnection()时使root用户成为去获取连接的用户。主要用于连接池连接非c3p0   
  的数据源时。Default: null-->   
  <property name="overrideDefaultUser">root</property>   
  <!--与overrideDefaultUser参数对应使用的一个参数。Default: null-->   
  <property name="overrideDefaultPassword">password</property>   
  <!--密码。Default: null-->   
  <property name="password"></property>   
  <!--定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:   
  测试的表必须在初始数据源的时候就存在。Default: null-->   
  <property name="preferredTestQuery">select id from test where id=1</property>   
  <!--用户修改系统配置参数执行前最多等待300秒。Default: 300 -->   
  <property name="propertyCycle">300</property>   
  <!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的   
  时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable   
  等方法来提升连接测试的性能。Default: false -->   
  <property name="testConnectionOnCheckout">false</property>   
  <!--如果设为true那么在取得连接的同时将校验连接的有效性。Default: false -->   
  <property name="testConnectionOnCheckin">true</property>   
  <!--用户名。Default: null-->   
  <property name="user">root</property>
ログイン後にコピー

Hibernate (Spring 管理) での設定:


<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">   
  <property name="driverClass"><value>oracle.jdbc.driver.OracleDriver</value></property>   
  <property name="jdbcUrl"><value>jdbc:oracle:thin:@localhost:1521:Test</value></property>   
  <property name="user"><value>Kay</value></property>   
  <property name="password"><value>root</value></property>   
  <!--连接池中保留的最小连接数。-->   
  <property name="minPoolSize" value="10" />   
  <!--连接池中保留的最大连接数。Default: 15 -->   
  <property name="maxPoolSize" value="100" />   
  <!--最大空闲时间,1800秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->   
  <property name="maxIdleTime" value="1800" />   
  <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->   
  <property name="acquireIncrement" value="3" />   
  <property name="maxStatements" value="1000" />   
  <property name="initialPoolSize" value="10" />   
  <!--每60秒检查所有连接池中的空闲连接。Default: 0 -->   
  <property name="idleConnectionTestPeriod" value="60" />   
  <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->   
  <property name="acquireRetryAttempts" value="30" />   
  <property name="breakAfterAcquireFailure" value="true" />   
  <property name="testConnectionOnCheckout" value="false" />   
  </bean>   
  ###########################   
  ### C3P0 Connection Pool###   
  ###########################   
  #hibernate.c3p0.max_size 2   
  #hibernate.c3p0.min_size 2   
  #hibernate.c3p0.timeout 5000   
  #hibernate.c3p0.max_statements 100   
  #hibernate.c3p0.idle_test_period 3000   
  #hibernate.c3p0.acquire_increment 2   
  #hibernate.c3p0.validate false   
  在hibernate.cfg.xml文件里面加入如下的配置:   
  <!-- 最大连接数 -->   
  <property name="hibernate.c3p0.max_size">20</property>   
  <!-- 最小连接数 -->   
  <property name="hibernate.c3p0.min_size">5</property>   
  <!-- 获得连接的超时时间,如果超过这个时间,会抛出异常,单位毫秒 -->   
  <property name="hibernate.c3p0.timeout">120</property>   
  <!-- 最大的PreparedStatement的数量 -->   
  <property name="hibernate.c3p0.max_statements">100</property>   
  <!-- 每隔120秒检查连接池里的空闲连接 ,单位是秒-->   
  <property name="hibernate.c3p0.idle_test_period">120</property>   
  <!-- 当连接池里面的连接用完的时候,C3P0一下获取的新的连接数 -->   
  <property name="hibernate.c3p0.acquire_increment">2</property>   
  <!-- 每次都验证连接是否可用 -->   
  <property name="hibernate.c3p0.validate">true</property>
ログイン後にコピー

DBCP 接続プール使用時に MySql 8 時間切断の解決策

l 設定ファイルを変更:

次のように変更:

<data-sources>  
      <data-source key="org.apache.struts.action.DATA_SOURCE"                             
      type="org.apache.commons.dbcp.BasicDataSource">  
      <set-property property="driverClassName" value="com.mysql.jdbc.Driver" />  
      <set-property property="description" value="wjjg" />  
      <set-property property="url" value="jdbc:mysql://localhost/wjjg?useUnicode=true&characterEncoding=GB2312" />  
      <set-property property="password" value="12345678" />  
      <set-property property="username" value="wjjg" />  
      <set-property property="maxActive" value="10" />  
      <set-property property="maxIdle" value="60000" />  
      <set-property property="maxWait" value="60000" />  
      <set-property property="defaultAutoCommit" value="true" />  
      <set-property property="defaultReadOnly" value="false" />    
      <set-property property="testOnBorrow" value="true"/>  
      <set-property property="validationQuery" value="select 1"/>  
</data-source>
ログイン後にコピー

その中で、testOnBorrowと validationQuery は重要です。
testOnBorrow は、データベース接続プールから接続を取得するときに接続の有効性をチェックすることを意味します。
validationQuery はチェックに使用される SQL ステートメントであり、「select 1」は高速に実行され、優れた検出ステートメントです。





以上がMySQL - c3p0 と DBCP 接続プールの使用によって引き起こされる MySql 8 時間の問題に対する詳細なコード解決策の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

MySQLユーザーとデータベースの関係 MySQLユーザーとデータベースの関係 Apr 08, 2025 pm 07:15 PM

MySQLデータベースでは、ユーザーとデータベースの関係は、アクセス許可と表によって定義されます。ユーザーには、データベースにアクセスするためのユーザー名とパスワードがあります。許可は助成金コマンドを通じて付与され、テーブルはCreate Tableコマンドによって作成されます。ユーザーとデータベースの関係を確立するには、データベースを作成し、ユーザーを作成してから許可を付与する必要があります。

MySQL:初心者向けのデータ管理の容易さ MySQL:初心者向けのデータ管理の容易さ Apr 09, 2025 am 12:07 AM

MySQLは、インストールが簡単で、強力で管理しやすいため、初心者に適しています。 1.さまざまなオペレーティングシステムに適した、単純なインストールと構成。 2。データベースとテーブルの作成、挿入、クエリ、更新、削除などの基本操作をサポートします。 3.参加オペレーションやサブクエリなどの高度な機能を提供します。 4.インデックス、クエリの最適化、テーブルパーティション化により、パフォーマンスを改善できます。 5。データのセキュリティと一貫性を確保するために、バックアップ、リカバリ、セキュリティ対策をサポートします。

NAVICATでデータベースパスワードを取得できますか? NAVICATでデータベースパスワードを取得できますか? Apr 08, 2025 pm 09:51 PM

NAVICAT自体はデータベースパスワードを保存せず、暗号化されたパスワードのみを取得できます。解決策:1。パスワードマネージャーを確認します。 2。NAVICATの「パスワードを記憶する」機能を確認します。 3.データベースパスワードをリセットします。 4.データベース管理者に連絡してください。

MySQLのクエリ最適化は、特に大規模なデータセットを扱う場合、データベースのパフォーマンスを改善するために不可欠です MySQLのクエリ最適化は、特に大規模なデータセットを扱う場合、データベースのパフォーマンスを改善するために不可欠です Apr 08, 2025 pm 07:12 PM

1.正しいインデックスを使用して、データの量を削減してデータ検索をスピードアップしました。テーブルの列を複数回検索する場合は、その列のインデックスを作成します。あなたまたはあなたのアプリが基準に従って複数の列からのデータが必要な場合、複合インデックス2を作成します2。選択した列のみを避けます。必要な列のすべてを選択すると、より多くのサーバーメモリを使用する場合にのみサーバーが遅くなり、たとえばテーブルにはcreated_atやupdated_atやupdated_atなどの列が含まれます。

Navicatプレミアムの作成方法 Navicatプレミアムの作成方法 Apr 09, 2025 am 07:09 AM

NAVICATプレミアムを使用してデータベースを作成します。データベースサーバーに接続し、接続パラメーターを入力します。サーバーを右クリックして、[データベースの作成]を選択します。新しいデータベースの名前と指定された文字セットと照合を入力します。新しいデータベースに接続し、オブジェクトブラウザにテーブルを作成します。テーブルを右クリックして、データを挿入してデータを挿入します。

MariadBのNAVICATでデータベースパスワードを表示する方法は? MariadBのNAVICATでデータベースパスワードを表示する方法は? Apr 08, 2025 pm 09:18 PM

Passwordが暗号化された形式で保存されているため、MariadbのNavicatはデータベースパスワードを直接表示できません。データベースのセキュリティを確保するには、パスワードをリセットするには3つの方法があります。NAVICATを介してパスワードをリセットし、複雑なパスワードを設定します。構成ファイルを表示します(推奨されていない、高リスク)。システムコマンドラインツールを使用します(推奨されません。コマンドラインツールに習熟する必要があります)。

MySQLでテーブルをコピーする方法 MySQLでテーブルをコピーする方法 Apr 08, 2025 pm 07:24 PM

MySQLでテーブルをコピーするには、新しいテーブルの作成、データの挿入、外部キーの設定、インデックスのコピー、トリガー、ストアドプロシージャ、および機能が必要です。特定の手順には、同じ構造を持つ新しいテーブルの作成が含まれます。元のテーブルからデータを新しいテーブルに挿入します。同じ外部キーの制約を設定します(元のテーブルに1つがある場合)。同じインデックスを作成します。同じトリガーを作成します(元のテーブルに1つがある場合)。同じストアドプロシージャまたは関数を作成します(元のテーブルが使用されている場合)。

mysqlを表示する方法 mysqlを表示する方法 Apr 08, 2025 pm 07:21 PM

次のコマンドでmysqlデータベースを表示します。サーバーに接続します:mysql -u username -pパスワードrun showデータベース。すべての既存のデータベースを取得するコマンド[データベース]を選択します。データベース名を使用します。テーブルを表示:表を表示します。テーブル構造を表示:テーブル名を説明してください。データを表示:[テーブル名]から[ *]を選択します。

See all articles