当前正在尝试使用java在MySQL 5.5数据库上存储大文件。我的主类叫做FileDatabaseTest。它有以下方法:使用Java的BufferedInputStream将大文件存储到MySQL数据库时获取java.lang.outOfMemoryError
import java.sql.*;
import java.io.*;
...
public class FileDatabaseTest {
...
private void uploadToDatabase(File file, String description) {
try {
PreparedStatement stmt = connection.prepareStatement(
"INSERT INTO FILES (FILENAME, FILESIZE, FILEDESCRIPTION, FILEDATA) " +
"VALUES (?, ?, ?, ?)");
stmt.setString(1, file.getName());
stmt.setLong(2, file.length());
stmt.setString(3, description);
stmt.setBinaryStream(4, new FileInputStream(file));
stmt.executeUpdate();
updateFileList();
stmt.close();
} catch(SQLException e) {
e.printStackTrace();
} catch(FileNotFoundException e) {//thrown by FileInputStream constructor
e.printStackTrace();
} catch(SecurityException e) { //thrown by FileInputStream constructor
e.printStackTrace();
}
}
...
}
该数据库只有一个表 - “文件”表,它有以下列。
ID - AUTOINCREMENT, PRIMARY KEY
FILENAME - VARCHAR(100)
FILESIZE - BIGINT
FILEDESCRIPTION - VARCHAR(500)
FILEDATA - LONGBLOB
上传小文件时程序工作正常,但是当我上传20MB等文件时,上传过程非常缓慢。于是,我把一个的FileInputStream里面的BufferedInputStream在下面的代码:
stmt.setBinaryStream(4, new BufferedInputStream(new FileInputStream(file));
上传过程变得非常快。就像将文件复制到另一个目录一样。但是,当我试图更上传文件超过400MB,我得到了以下错误:
Exception in thread "Thread-5" java.lang.OutOfMemoryError: Java heap space
at com.mysql.jdbc.Buffer.ensureCapacity(Buffer.java:156)
at com.mysql.jdbc.Buffer.writeBytesNoNull(Buffer.java:514)
at com.mysql.jdbc.PreparedStatement.escapeblockFast(PreparedStatement.java:1169)
at com.mysql.jdbc.PreparedStatement.streamToBytes(PreparedStatement.java:5064)
at com.mysql.jdbc.PreparedStatement.fillSendPacket(PreparedStatement.java:2560)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2401)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2345)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2330)
at FileDatabaseTest$2.run(FileDatabaseTest.java:312)
at java.lang.Thread.run(Thread.java:662)
所以我使用嵌入式Apache的Derby数据库,而不是MySQL的审判,我没有得到这个错误。我能够使用BufferedInputStream在Derby数据库中上传500MB到1.5G的文件。我还观察到,当使用BufferedInputStream和MySQL服务器上传大文件时,JVM占用大量内存,而当我在Derby数据库中使用它时,JVM的内存使用率保持在85MB到100MB左右。
我对MySQL比较新,我只是使用它的默认配置。我在配置中唯一改变的是“max_allowed_packet”大小,所以我可以上传2GB文件到数据库。所以我想知道错误来自哪里。它是MySQL或MySQL连接器/ J的错误吗?或者我的代码有什么问题?
我想在这里实现的是能够使用java将大文件(最多2GB)上传到MySQL服务器,而不增加Java堆空间。
Mysql jdbc驱动程序有一个名为“maxAllowedPacket”的选项,默认情况下该选项与max_allowed_packet的值匹配。所以这听起来像是驱动程序在内部为整个数据包分配了足够的缓冲空间。 – Vadim
我已经尝试更改“maxAllowedPacket”属性,但是当我将其更改为更小的值时,发送大于“maxAllowedProperty”值的文件时出现错误。当我将其更改为更高值时,上传大文件时出现java.lang.outOfMemory错误。我观察到的是,在执行sql语句之前,使用MySQL,java会将整个文件的内容读入内存,我认为这是上传大文件时出现outOfMemory错误的原因。有没有办法阻止java发送到MySQL之前将整个文件加载到内存中? – Esjee
你解决了这个问题吗? – Rafaesp