[請問] jdbc連mysql隔一段時間就出現連線失敗
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
01/04 11:08, 1F
→
01/05 01:35, , 2F
01/05 01:35, 2F
→
01/05 10:52, , 3F
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
01/05 18:34, 6F
→
01/05 18:35, , 7F
01/05 18:35, 7F
→
01/06 15:35, , 8F
01/06 15:35, 8F
→
01/06 19:42, , 9F
01/06 19:42, 9F
→
01/06 22:14, , 10F
01/06 22:14, 10F
→
01/07 09:53, , 11F
01/07 09:53, 11F
→
01/09 16:10, , 12F
01/09 16:10, 12F
→
01/09 16:14, , 13F
01/09 16:14, 13F