PHP+Ajax批量插入MySQL仅能插入111行问题求助
场景与代码
表单结构
通过弹窗以tdname[rowid]形式向表格添加数据,生成的表单结构如下:
<form method="post" id="user_form"> <div class="table-responsive"> <table id="user_data"> <tbody> <tr id="row_1"> <td>1 <input type="hidden" name="hidden_pid[]" id="pid1" class="pid" value="1"></td> <td>K-60 <input type="hidden" name="hidden_p_code[]" id="p_code1" class="p_code" value="K-60"></td> <td>Product 1<input type="hidden" name="hidden_p_name[]" id="p_name1" value="Product 1"></td> <td> <input type="hidden" name="hidden_dekorA[]" id="dekorA1" value=""></td> <td class="p_quantity">1 <input type="hidden" name="hidden_p_quantity[]" class="p_quantity1" id="p_quantity1" min="0" max="2500" step="1" value="1" data-type="1"></td> <td>23.40 <input type="hidden" name="hidden_p_listprice[]" class="p_listprice1" id="p_listprice1" value="23.40" data-type="23.40"></td> <td>23.40 <input type="hidden" name="hidden_p_netprice[]" id="p_netprice1" value="23.40"></td> <td class="p_total">23.40 <input type="hidden" name="hidden_p_total[]" class="p_total" id="p_total1" value="23.40" for="1"></td> <td>122 <input type="hidden" name="hidden_preorderno[]" id="preorderno1" class="preorderno" value="122"></td> </tr> ... </tbody></table> </div> <div align="center"> <button type="submit" name="insert" id="insert" class="btn btn-primary">Confirm Order</button> </div> </form>
Ajax提交代码
使用Ajax POST方法将数据发送至insert.php:
<script> $(document).ready(function(){ $('#user_form').on('submit', function(event){ event.preventDefault(); var form_data = $("[name='hidden_pid[]'],[name='hidden_p_code[]'],[name='hidden_p_name[]'],[name='hidden_dekorA[]'],[name='hidden_p_quantity[]'],[name='hidden_p_listprice[]'],[name='hidden_p_netprice[]'],[name='hidden_p_total[]'],[name='hidden_preorderno[]']").serialize(); $.ajax({ type:"POST", url:"insert.php", data : (form_data), success:function(data) { alert('OK'); }, error:function(data){ alert('hata'); } }); }); }); </script>
后端插入代码(insert.php)
通过名为NEWLIST的存储过程执行插入操作:
$db = new PDO("mysql:host=localhost;dbname=;charset=utf8;","username","pass"); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); try{ $sp='NEWLIST'; $sql=sprintf('SELECT group_concat(DISTINCT ":",`parameter_name`) as `placeholders` FROM `information_schema`.`parameters` WHERE `SPECIFIC_NAME`="%s" and `specific_schema`="databasename"', $sp); $res=$db->query($sql)->fetch(PDO::FETCH_OBJ); $placeholders=$res->placeholders; $sql=sprintf('call `%s`( %s );', $sp, $placeholders); $keys=explode( ',', $placeholders ); $size = count($_REQUEST['hidden_pid']); $count = 0; $stmt=$db->prepare($sql); while($count < $size){ $main_arr = array( ':pid' => $_REQUEST['hidden_pid'][$count], ':p_code' => $_REQUEST['hidden_p_code'][$count], ':p_name' => $_REQUEST['hidden_p_name'][$count], ':dekorA' => $_REQUEST['hidden_dekorA'][$count], ':p_quantity' => $_REQUEST['hidden_p_quantity'][$count], ':p_listprice' => $_REQUEST['hidden_p_listprice'][$count], ':p_netprice' => $_REQUEST['hidden_p_netprice'][$count], ':p_total' => $_REQUEST['hidden_p_total'][$count], ':preorderno' => $_REQUEST['hidden_preorderno'][$count], ':yetkili' => $_SESSION['id'] ); $count++; $data=array_combine($keys, array_values($main_arr)); $stmt->execute($data); } $db->commit(); } catch( PDOException $e ){ return "Insert failed: " . $e->getMessage(); } $db = null;
问题描述
当前代码可正常运行,但添加数百行数据后,Ajax能正常传递数据到insert.php,但MySQL仅能插入最多111行。已将max_allowed_packet设置为500MB,问题仍在两台服务器(测试服务器:AMD Ryzen7 2700/16GB RAM;树莓派4:BCM2711/4GB RAM)上出现,推测问题出在insert.php中。
解决方案
核心原因:PHP的max_input_vars限制
PHP默认max_input_vars值为1000,每行数据包含9个字段(hidden_pid[]到hidden_preorderno[]),111行刚好对应999个变量,超过1000的部分会被PHP自动截断,导致$_REQUEST中仅能获取到前111行数据。
解决步骤
修改php.ini配置
找到php.ini文件,修改max_input_vars为更大的值(如5000或10000):max_input_vars = 5000修改后重启PHP服务(如Apache、Nginx-FPM等)。
临时代码设置(可选)
如果无法修改php.ini,可在insert.php开头添加以下代码临时调整(部分主机可能禁用此函数):ini_set('max_input_vars', 5000);代码优化(可选,提升性能)
当前循环调用存储过程的方式效率较低,可优化为批量插入:- 调整存储过程,使其支持批量参数输入;
- 或者构造批量插入的SQL语句,减少数据库交互次数,同时避免频繁调用存储过程的开销。
验证方法
在insert.php开头添加代码,打印$_REQUEST['hidden_pid']的数量:
echo count($_REQUEST['hidden_pid']); exit;
如果输出为111,即可确认是max_input_vars限制导致的问题。
内容的提问来源于stack exchange,提问作者muhtarkator

