Description:
i´m having trouble storing a blob of more than 16mb into the database.
server is 4.0.16 on linux, driver is 3.0.9 or snaptshots from
Jan 6. ´04 or Jan 8. ´04
show variables;
gives a max_allowed_packet value of 512mb
table looks like this:
mysql> describe bintest;
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+----------------+
| uid | bigint(20) | | PRI | NULL | auto_increment |
| data | longblob | YES | | NULL | |
I have a simple unit test that inserts one blob into the DB an the reselects it back, in order to compare the result to the Array previously inserted.
The comparison shows an offset of 1 in the data, if the array is larger than 15mb (otherwise, everything works as expected) like this:
first array: -39 -41 36 -119 -14 31 36 66 -47 -56 -93 102 -25 -121 -125
47
second array: 0 -39 -41 36 -119 -14 31 36 66 -47 -56 -93 102 -25 -121 -125
How to repeat:
Use this TestCase to reproduce:
package tests;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import junit.framework.TestCase;
import org.gjt.mm.mysql.Driver;
public class MaxSizeTest extends TestCase
{
private static final String URL = "jdbc:mysql://someServer/connectorjtest?user=someUser&password=somePassword";
public MaxSizeTest(String arg0)
{
super(arg0);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(MaxSizeTest.class);
}
protected void setUp() throws Exception
{
super.setUp();
Class.forName(Driver.class.getName());
java.sql.Driver d = DriverManager.getDriver(URL);
System.err.println("Testing Driver " + d.getMajorVersion() + "." + d.getMinorVersion());
}
protected void tearDown() throws Exception
{
super.tearDown();
}
public void testAll() throws Exception
{
testArray(TestBlob.bin);
}
private void testArray(byte[] bs) throws Exception
{
System.err.println("query test with " + bs.length + " bytes");
Connection c = DriverManager.getConnection(URL);
//
java.sql.PreparedStatement s = c.prepareStatement("DELETE FROM bintest;");
s.execute();
//
s = c.prepareStatement("INSERT INTO bintest VALUES (?,?);");
long id = System.currentTimeMillis();
s.setLong(1, id);
s.setBytes(2, bs);
//
s.execute();
//
ResultSet rs = c.prepareStatement("SELECT * FROM bintest WHERE uid=" + id).executeQuery();
if (rs.next())
{
long l = rs.getLong(1);
assertEquals(l, id);
byte[] b = rs.getBytes(2);
assertEquals(b.length, bs.length);
// compare arrays
for (int i = 0; i < b.length; i++)
{
if (b[i] != bs[i])
{
System.err.println("byte: " + i);
doFail(b, bs);
}
}
}
else
fail();
}
private void doFail(byte[] b, byte[] bs)
{
printStart("first array: ", bs);
printStart("second array: ", b);
fail();
}
private void printStart(String string, byte[] b)
{
System.err.print(string);
for (int i = 0; i < 16; i++)
{
byte c = b[i];
System.err.print(String.valueOf((int) c) + " ");
}
System.err.println("");
}
static class TestBlob
{
public static byte[] bin = new byte[1024 * 1024 * 16];
static {
System.err.println("preparing array");
fillArray(bin);
System.err.println("preparing array done");
}
private static void fillArray(byte[] array)
{
for (int i = 0; i < array.length; i++)
{
array[i] = (byte) (Math.random() * 256);
}
}
}
}
Suggested fix:
the fact, that this only happens if the array is near to 16m lets us suspect something around packet chunking or something like that.