在 PHP 的 MySQLi 扩展中,mysqli_stmt::send_long_data 是一个用于发送大数据(如大文本、大二进制数据等)到 MySQL 数据库的函数。当处理大规模的数据插入时,常规的 bind_param() 方法可能会受到数据大小限制,这时候 send_long_data() 就显得尤为重要。本文将介绍 mysqli_stmt::send_long_data 的基本用法以及使用时的注意事项。
<span><span>mysqli_stmt::</span><span><span class="hljs-title function_ invoke__">send_long_data</span></span><span>(</span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-variable">$param_nr</span></span><span>, </span><span><span class="hljs-keyword">string</span></span><span> </span><span><span class="hljs-variable">$data</span></span><span>): </span><span><span class="hljs-keyword">bool</span></span><span>
</span></span>
$param_nr:表示要发送的数据的参数编号。它对应于 SQL 语句中 ? 占位符的位置,从 0 开始计数。
$data:表示要发送的大数据,通常是一个大字符串或二进制数据。
返回值:成功时返回 true,失败时返回 false。
send_long_data 主要用于将大量数据传输到 MySQL 数据库中。通常情况下,mysqli_stmt::bind_param() 用于绑定参数,但是如果数据量较大(例如,大文件的内容、大文本字段等),则会受到 PHP 配置文件中 max_allowed_packet 的限制。为了避免这种限制,可以使用 send_long_data 方法将数据分块发送到 MySQL 数据库。
假设我们有一个表格,结构如下:
<span><span><span class="hljs-keyword">CREATE</span></span><span> </span><span><span class="hljs-keyword">TABLE</span></span><span> files (
id </span><span><span class="hljs-type">INT</span></span><span> AUTO_INCREMENT </span><span><span class="hljs-keyword">PRIMARY</span></span><span> KEY,
name </span><span><span class="hljs-type">VARCHAR</span></span><span>(</span><span><span class="hljs-number">255</span></span><span>),
file_data LONGBLOB
);
</span></span>
在这个表中,我们存储文件的名称以及对应的文件二进制数据。我们通过以下步骤来插入大文件数据。
<span><span><span class="hljs-meta"><?php</span></span><span>
</span><span><span class="hljs-comment">// 创建数据库连接</span></span><span>
</span><span><span class="hljs-variable">$mysqli</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">mysqli</span></span><span>(</span><span><span class="hljs-string">"localhost"</span></span><span>, </span><span><span class="hljs-string">"username"</span></span><span>, </span><span><span class="hljs-string">"password"</span></span><span>, </span><span><span class="hljs-string">"database"</span></span><span>);
</span><span><span class="hljs-comment">// 检查连接</span></span><span>
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$mysqli</span></span><span>->connect_error) {
</span><span><span class="hljs-keyword">die</span></span><span>(</span><span><span class="hljs-string">"连接失败: "</span></span><span> . </span><span><span class="hljs-variable">$mysqli</span></span><span>->connect_error);
}
</span><span><span class="hljs-comment">// 准备 SQL 语句</span></span><span>
</span><span><span class="hljs-variable">$stmt</span></span><span> = </span><span><span class="hljs-variable">$mysqli</span></span><span>-></span><span><span class="hljs-title function_ invoke__">prepare</span></span><span>(</span><span><span class="hljs-string">"INSERT INTO files (name, file_data) VALUES (?, ?)"</span></span><span>);
</span><span><span class="hljs-comment">// 绑定第一个参数(文件名)</span></span><span>
</span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">bind_param</span></span><span>(</span><span><span class="hljs-string">"s"</span></span><span>, </span><span><span class="hljs-variable">$name</span></span><span>);
</span><span><span class="hljs-comment">// 读取文件数据</span></span><span>
</span><span><span class="hljs-variable">$filePath</span></span><span> = </span><span><span class="hljs-string">'large_file.txt'</span></span><span>;
</span><span><span class="hljs-variable">$fileData</span></span><span> = </span><span><span class="hljs-title function_ invoke__">file_get_contents</span></span><span>(</span><span><span class="hljs-variable">$filePath</span></span><span>);
</span><span><span class="hljs-comment">// 发送大数据</span></span><span>
</span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">send_long_data</span></span><span>(</span><span><span class="hljs-number">1</span></span><span>, </span><span><span class="hljs-variable">$fileData</span></span><span>);
</span><span><span class="hljs-comment">// 设置文件名</span></span><span>
</span><span><span class="hljs-variable">$name</span></span><span> = </span><span><span class="hljs-title function_ invoke__">basename</span></span><span>(</span><span><span class="hljs-variable">$filePath</span></span><span>);
</span><span><span class="hljs-comment">// 执行 SQL 语句</span></span><span>
</span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">execute</span></span><span>();
</span><span><span class="hljs-comment">// 关闭连接</span></span><span>
</span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">close</span></span><span>();
</span><span><span class="hljs-variable">$mysqli</span></span><span>-></span><span><span class="hljs-title function_ invoke__">close</span></span><span>();
</span><span><span class="hljs-meta">?></span></span><span>
</span></span>
在上面的代码中,我们通过 bind_param() 方法绑定了文件名(s 表示字符串类型)。文件数据是通过 send_long_data() 方法发送的,这样就可以传输大文件数据。
分块发送数据:send_long_data 会将数据分块发送到 MySQL,而不会像传统的 bind_param() 一样一次性将数据全部绑定。当数据较大时,使用 send_long_data 可以避免内存占用过高和 PHP 的执行时间限制。
支持大数据类型:send_long_data 主要用于 LONGBLOB、LONGTEXT 类型的数据传输,尤其是在上传或插入大文件时。
参数编号:send_long_data 使用参数编号来标识要发送的数据块。编号从 0 开始计数,所以在多次调用 send_long_data 时,需确保正确的参数编号。
MySQL 配置限制:在使用 send_long_data 时,需要注意 MySQL 配置中的 max_allowed_packet 参数的大小。如果传输的数据超过此限制,插入会失败。可以通过以下 SQL 语句检查当前配置:
<span><span><span class="hljs-keyword">SHOW</span></span><span> VARIABLES </span><span><span class="hljs-keyword">LIKE</span></span><span> </span><span><span class="hljs-string">'max_allowed_packet'</span></span><span>;
</span></span>
若需要更改该值,可以在 MySQL 配置文件中修改:
<span><span><span class="hljs-attr">max_allowed_packet</span></span><span>=</span><span><span class="hljs-number">64</span></span><span>M
</span></span>
PHP 配置限制:此外,PHP 配置文件中的 upload_max_filesize 和 post_max_size 参数也可能会限制文件上传的大小。在使用 send_long_data 时,确保这些配置足够大。
数据库连接的超时设置:由于 send_long_data 会分块传输大数据,因此长时间的数据库操作可能导致连接超时。可以通过调整 MySQL 或 PHP 的超时设置来避免这种情况。
数据传输的顺序:send_long_data 的调用顺序与绑定参数的顺序相一致。在多次调用时,确保每次发送的数据对应正确的参数编号。
mysqli_stmt::send_long_data 是一个非常实用的函数,尤其是在需要插入大文件或大数据时,它能够有效解决传统参数绑定方法的局限性。通过合理使用该函数,可以确保大数据的顺利插入,同时避免内存不足或传输超时的问题。然而,使用时也需要注意 MySQL 和 PHP 的相关配置,确保数据传输不受限制。