當前正在嘗試使用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