2010-09-20 21 views
6

Tôi biết rằng để chèn các giá trị lớn hơn max_allowed_packet byte vào cơ sở dữ liệu MySQL, giải pháp mặc định sẽ đảm bảo rằng cả biến số khách hàng và phía máy chủ max_allowed_packet đều lớn hơn đoạn dữ liệu mà truy vấn chèn vào DB.Có cách nào để chèn một giá trị lớn trong một DB mysql mà không thay đổi max_allowed_packet?

Tuy nhiên, có cách nào để làm như vậy mà không cần thay đổi biến phía máy chủ được đề cập ở trên không? Điều này sẽ hữu ích khi tôi phải chèn dữ liệu vào cơ sở dữ liệu được lưu trữ trong một ISP không cho phép tôi thay đổi giới hạn max_allowed_packet.

Một câu hỏi liên quan khác: giới hạn MySql longblob là 4GB, nhưng giới hạn max_allowed_packet là 1GB. Vì vậy, có thể chèn các giá trị lớn hơn 1GB trong cột bảng longblob không?

Trả lời

11

Gần đây, tôi đã gặp phải sự cố này. Trong trường hợp của tôi, máy chủ của max_allowed_packet là 1 MB và tôi không thể làm gì để thay đổi nó. Và tôi đã chèn một số dữ liệu ngay trên 1 MB. Tôi tìm thấy hai ứng cử viên giải pháp.

1) Trước tiên, sử dụng JDBC. Kể từ MySQL Connector/J v3.1.9, có một vài thông số mà bạn có thể thiết lập, đây là bộ của tôi về các thông số trong URL JDBC:

Nối những:

blobSendChunkSize=50000&useServerPrepStmts=true&emulateUnsupportedPstmts=false&maxAllowedPacket=20000000 

Kết quả trong URL JDBC :

jdbc:mysql://serverip:3306/databasename?noDatetimeStringSync=true&blobSendChunkSize=50000&useServerPrepStmts=true&emulateUnsupportedPstmts=false&maxAllowedPacket=20000000 

Sau đó, bạn phải sử dụng PreparedStatement làm chèn của bạn, và sử dụng InputStream để vượt qua các nội dung byte như một tham số để setObject. Lưu ý rằng setObject sử dụng mảng byte sẽ không cho phép chia tách blob. Sự kết hợp của các tham số, máy chủ MySQL gần đây (5.0.45 hoặc mới hơn), và InputStream sẽ gửi dữ liệu blob bằng cách sử dụng cơ chế LONG DATA, tách các đốm màu theo blobSendChunkSize.

Giải pháp JDBC hoạt động và tôi đã thử nghiệm nó.

2) Bây giờ, ứng cử viên thứ hai, là sử dụng trình điều khiển mysqli của PHP và sử dụng mysqli_send_long_data. Để thuận tiện cho bạn, hãy sao chép từ ví dụ thủ công PHP:

<?php 
$stmt = $mysqli->prepare("INSERT INTO messages (message) VALUES (?)"); 
$null = NULL; 
$stmt->bind_param("b", $null); 
$fp = fopen("messages.txt", "r"); 
while (!feof($fp)) { 
    $stmt->send_long_data(0, fread($fp, 8192)); 
} 
fclose($fp); 
$stmt->execute(); 
?> 
+1

Chỉ cần cố gắng mysqli để lưu trữ một tập tin 27mb trên max_allowed_packet 1mb.Câu trả lời tuyệt vời, chúng tôi đã làm việc trên một công việc xung quanh cho điều này trong gần một tuần. – shmeeps

+0

Không thể đặt các thông số này chỉ cho giao dịch/kết nối hiện tại? Có thể sử dụng 'SET ...'? Tôi thích điều này hơn là thay đổi URL JDBC. –

+0

Làm việc tuyệt vời khi chỉ thêm hai tham số này sử dụngServerPrepStmts = true & maxAllowedPacket = 20000000. Tôi đã thấy 'java.sql.SQLException: Tham số của câu lệnh chuẩn bị được thiết lập thông qua mysql_send_long_data() dài hơn' max_allowed_packet 'bytes', điều này thật lạ khi tôi sử dụng blobSendChunkSize. – Rishi

-1

Tôi không nghĩ rằng có một cách. Có thể tách các đốm màu sẽ làm các trick.

Nhưng tôi nghĩ rằng đọc bài viết này http://blogs.msdn.com/b/oldnewthing/archive/2007/03/01/1775759.aspx từ Reymond Chen là câu trả lời hay nhất cho câu hỏi của bạn.

Cơ sở dữ liệu quan hệ không được thiết kế cho loại sử dụng đó. Nếu bạn cần lưu trữ một gigabyte + blob trong một cơ sở dữ liệu, thì tốt hơn là lưu trữ nó trên NFS và chỉ có một chuỗi vị trí tệp ngắn trong DB của bạn. Sẽ giúp bạn tiết kiệm rất nhiều rắc rối trên đường.

+0

Câu hỏi thứ hai của tôi là tò mò hơn, câu hỏi chính là câu hỏi đầu tiên. Tôi không có ý định đặt một blob 3GB trong một cột duy nhất ... và tôi không nghĩ câu hỏi đầu tiên của tôi có liên quan đến việc vi phạm các giới hạn của hệ điều hành. Tôi có nghĩa là, nó sẽ hữu ích để đặt một blob 2MB trong một cơ sở dữ liệu mà max_allowed_packet chỉ là 1MB, khi tôi không thể thay đổi biến này ... –

Các vấn đề liên quan