[請問] jdbc連mysql隔一段時間就出現連線失敗

看板java作者 (tnsshnews)時間11年前 (2013/01/04 09:42), 編輯推噓3(3010)
留言13則, 7人參與, 最新討論串1/1
0. 問題描述 - 目的: 將收到的Request網路封包資料寫入資料庫。 - 啟動: 一切正常, 立即製造網路封包皆能正常寫入資料庫。 - 發生時間點: 有時當隔一段時間(不長且不固定)就會出現Communications link failure, 有時一起動之後, 大量傳送封包也偶而會發生Communications link failure。 - 錯誤訊息: 2013-01-03 03:49:56.798 ERROR [Thread-1] -- SQLException com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure The last packet successfully received from the server was 4,415,181 milliseconds ago. The last packet sent successfully to the server was 35 milliseconds ago. at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) 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:3589) at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3478) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4019) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2734) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155) at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1379) at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:169) at com.apt.deliverSM.smpp.MOReceiver.MOImport(MOReceiver.java:216) at com.apt.deliverSM.smpp.MOReceiver.autowrite(MOReceiver.java:119) at com.apt.deliverSM.smpp.MOReceiver.run(MOReceiver.java:49) at java.lang.Thread.run(Thread.java:619) Caused by: java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost. at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3039) at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3489) ... 12 more 1. 建立連線程式碼 String userName = "myUsername"; String password = "myPassword"; String url = "jdbc:mysql://localhost:3306/myDatabaseName"; Class.forName("com.mysql.jdbc.Driver").newInstance(); conn = DriverManager.getConnection(url,userName,password); System.out.println("Database connection established"); 2. 資料寫入資料庫程式碼 PreparedStatement ps = conn.prepareStatement(sql); ps.setTimestamp(1, new Timestamp(new Date().getTime())); ps.setString(2, tokens[0]); ps.setString(3, tokens[1]); ps.setString(4, tokens[2]); ps.setString(5, tokens[3]); ps.setString(6, ""); ps.setString(7, ""); ps.setInt(8, 0); ps.execute(); ps.close(); conn.close(); 3. MySql設定檔(my.cnf) [client] #password = your_password port = 3306 socket = /var/lib/mysql/mysql.sock # The MySQL server [mysqld] long_query_time = 10 log-slow-queries = /mysql_data/mysqllog/slow_query.log #log-queries-not-using-indexes = true port = 3306 socket = /var/lib/mysql/mysql.sock skip-locking key_buffer_size = 32M max_allowed_packet = 32M table_open_cache = 2048 sort_buffer_size = 16M read_buffer_size = 8M read_rnd_buffer_size = 16M myisam_sort_buffer_size = 128M thread_cache_size = 32 query_cache_size = 128M tmp_table_size = 128M # Try number of CPU's*2 for thread_concurrency thread_concurrency = 16 innodb_thread_concurrency=16 #skip-networking init-connect='insert into accesslog.accesslog(conn_id,time,localname,matchname) values(connection_id(),now(),user(),current_user())' # Replication Master Server (default) # binary logging is required for replication #log-bin=mysql-bin log-bin=/mysql_data/mysqllog/mysql-bin.log expire_logs_days = 60 datadir=/mysql_data/mysqldata/ # required unique id between 1 and 2^32 - 1 # defaults to 1 if master-host is not set # but will not function as a master if omitted server-id = 1 # Replication Slave (comment out master section to use this) # # To configure this host as a replication slave, you can choose between # two methods : # # 1) Use the CHANGE MASTER TO command (fully described in our manual) - # the syntax is: # # CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>, # MASTER_USER=<user>, MASTER_PASSWORD=<password> ; # # where you replace <host>, <user>, <password> by quoted strings and # <port> by the master's port number (3306 by default). # # Example: # # CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306, # MASTER_USER='joe', MASTER_PASSWORD='secret'; # # OR # # 2) Set the variables below. However, in case you choose this method, then # start replication for the first time (even unsuccessfully, for example # if you mistyped the password in master-password and the slave fails to # connect), the slave will create a master.info file, and any later # change in this file to the variables' values below will be ignored and # overridden by the content of the master.info file, unless you shutdown # the slave server, delete master.info and restart the slaver server. # For that reason, you may want to leave the lines below untouched # (commented) and instead use CHANGE MASTER TO (see above) # # required unique id between 2 and 2^32 - 1 # (and different from the master) # defaults to 2 if master-host is set # but will not function as a slave if omitted #server-id = 2 # # The replication master for this slave - required #master-host = <hostname> # # The username the slave will use for authentication when connecting # to the master - required #master-user = <username> # # The password the slave will authenticate with when connecting to # the master - required #master-password = <password> # # The port the master is listening on. # optional - defaults to 3306 #master-port = <port> # # binary logging - not required for slaves, but recommended #log-bin=mysql-bin # # binary logging format - mixed recommended binlog_format=mixed # Point the following paths to different dedicated disks #tmpdir = /tmp/ #log-update = /path-to-dedicated-directory/hostname # Uncomment the following if you are using InnoDB tables innodb_data_home_dir = /mysql_data/mysqldata/ innodb_data_file_path = ibdata1:10M:autoextend #innodb_log_group_home_dir = /mysql_data/mysqllog/ # You can set .._buffer_pool_size up to 50 - 80 % # of RAM but beware of setting memory usage too high innodb_buffer_pool_size = 1G #innodb_additional_mem_pool_size = 64M # Set .._log_file_size to 25 % of buffer pool size #innodb_log_file_size = 100M #innodb_log_buffer_size = 8M #innodb_flush_log_at_trx_commit = 1 innodb_lock_wait_timeout = 120 #modify by ryan optimization and tuning wait_timeout=1000 interactive_timeout=120 join_buffer_size=16M query_cache_limit=8M table_cache=128 [mysqldump] quick max_allowed_packet = 32M [mysql] no-auto-rehash # Remove the next comment character if you are not familiar with SQL #safe-updates [myisamchk] key_buffer_size = 512M sort_buffer_size = 512M read_buffer = 8M write_buffer = 8M [mysqlhotcopy] interactive-timeout 4. 補充說明 本來以為是不是因為每次寫入資料之後, 連線沒有關閉而導致Timeout, 但後來每筆資料都重新建立新連線, 一寫完資料就立刻關閉連線釋放資源, 但問題依然一樣, 之前也google了許多類似案例, 也都沒有任何幫助。 而且如果是timeout造成的問題, 應該是因為網路很慢導致斷線中斷, 但我的情況是才剛要建立新連線就發生無法連線, 怎麼想都應該不是timeout造成的問題, 網路上一堆文章都說是timeout設定錯誤, 拜託各位神人解惑, 感激不盡!! 5. 參考資料 http://stackoverflow.com/questions/6865538/solving-a-communications-link-failure-with-jdbc-and-mysql -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 203.79.199.63

01/04 11:08, , 1F
==.=== 直覺是套 connection pool 就可以解決
01/04 11:08, 1F

01/05 01:35, , 2F
你是不是同時有很多 Object 對這個 connection 寫資料?
01/05 01:35, 2F

01/05 10:52, , 3F
程式是一個thread, 會一直執行Listen封包
01/05 10:52, 3F

01/05 10:54, , 4F
只要有新封包, 就會建立新連線, 寫入之後馬上關閉
01/05 10:54, 4F

01/05 11:19, , 5F
馬上關閉沒有那麼「馬上」阿
01/05 11:19, 5F

01/05 18:34, , 6F
樓上正解。不改程式的做法,就是把max_connextions開超大
01/05 18:34, 6F

01/05 18:35, , 7F
但治標不治本XD
01/05 18:35, 7F

01/06 15:35, , 8F
所以要使用connection pool?
01/06 15:35, 8F

01/06 19:42, , 9F
一開始就跟你講了阿...... [攤手]
01/06 19:42, 9F

01/06 22:14, , 10F
mysql 的設定看起來很『預設』,資料長大了會後悔的xd
01/06 22:14, 10F

01/07 09:53, , 11F
WINDOWS的TCP/IP的連線不會那麼快釋放~所以用POOL比較好
01/07 09:53, 11F

01/09 16:10, , 12F
可以只用一個connection,程式啟動時建立
01/09 16:10, 12F

01/09 16:14, , 13F
這樣封包來只需要執行寫入就可以了,若頂不住就得上pool了
01/09 16:14, 13F
文章代碼(AID): #1GvZDkIG (java)