PHP插入MySQL的数据可正常读取但phpMyAdmin无对应记录问题咨询
问题描述
我有一个用于向数据库提交POST数据的简单PHP页面,实际仅用于调试,正式应用的POST请求来自Arduino:
SamplePost.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> </head> <body> <form action="data_post.php" method="post"> <table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2"> <tbody> <tr> <td>Name(Temp):</td> <td><input name="username" type="text"></td> <td></td> </tr> <tr> <td>Age(co2):</td> <td><input name="age" type="text"></td> <td></td> </tr> <tr> <td>UVIndex:</td> <td><input name="uvindex" type="text"></td> <td></td> </tr> <tr> <td>MQ2:</td> <td><input name="mq2" type="text"></td> <td></td> </tr> <tr> <td></td> <td></td> <td><input type="submit"></td> </tr> </tbody> </table> <br> </form> </body> </html>
最近20天Arduino应用一直无法正常提交数据,我用该页面调试时,意外发现PHP中配置的数据库用户名填写有误。奇怪的是这套代码已经正常运行多年,我不记得修改过PHP里的数据库用户名配置,不过先不管这个问题,数据提交的接口代码如下:
data_post.php
<?php $user = 'myusr'; $password = 'mypwd'; $server = 'localhost'; $database = 'mydb'; $pdo = new PDO("mysql:host=$server;dbname=$database", $user, $password); $username=$_POST['name']; $age=$_POST['age']; $uvindex=$_POST['uvindex']; $mq2=$_POST['mq2']; $sql = "INSERT INTO example (name,age,uvindex,mq2,beer) VALUES (:username, :age, :uvindex, :mq2, 'NO')"; $stmt = $pdo->prepare($sql); $stmt->bindParam(":username", $username); $stmt->bindParam(":age", $age); $stmt->bindParam(":uvindex", $uvindex); $stmt->bindParam(":mq2", $mq2); $result = $stmt->execute(array(':username'=>$username, ':age'=>$age, ':uvindex'=>$uvindex, ':mq2'=>$mq2)); if($result) { echo "Your text has been posted"; }// end if else { echo '0 results'; }// end else file_put_contents("arduinopost.txt",$username); ?>
我修正代码里的数据库用户名后,通过SamplePost.html提交测试,PHP返回了插入成功的提示,刷新数据库查询页面query.php也能看到新提交的记录,query.php代码如下:
query.php
<html> <body> <?php $servername = "localhost"; $username = "myusr"; $password = "mypwd"; $dbname = "mydb"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } $sql = "SELECT * FROM example where id > (SELECT MAX(id) - 20 FROM example)"; $result = $conn->query($sql); if ($result->num_rows > 0) { // output data of each row while($row = $result->fetch_assoc()) { echo "id=" . $row["id"]. ". Temp=" . $row["name"]. ". CO2PPM=" . $row["age"]. ". UVIndex=" . $row["uvindex"]. ". MQ2R=" . $row["mq2"]. ". Timestamp=" . $row["timestamp"]. "<br>"; } } else { echo "0 results"; } $conn->close(); ?> </body> </html>
但奇怪的问题出现了:我通过phpMyAdmin查看数据库时,完全找不到这条新插入的记录,但query.php页面多次刷新都能正常展示该数据。为什么PHP可以从数据库读取到数据,phpMyAdmin里却看不到对应记录?
我附了phpMyAdmin的截图,里面的记录已经按时间戳降序排列,按理应该能展示最新的记录对吧?
另外现在Arduino应用已经恢复正常提交,我在query.php页面可以看到最新的提交记录,但phpMyAdmin里还是看不到这些记录。我猜想原因可能是某个很基础的配置问题,但担心该问题和之前Arduino无法提交的故障有关联,不过现在至少数据提交功能已经恢复正常了。

问题解答
这是数据库使用场景中非常典型的多端数据不一致问题,大概率属于配置层面的低级错误,可按以下优先级排查:
- 优先排查是否连接到不同的MySQL实例
这是概率最高的原因:PHP代码中连接数据库用的是localhost,默认走Unix Socket连接MySQL,而很多phpMyAdmin的默认配置会用127.0.0.1走TCP连接,如果你的服务器上同时运行了两个MySQL实例(比如集成环境自带的和手动编译安装的、或者docker部署的和宿主机原生的),两个实例中存在同名的mydb库和example表,就会出现PHP写入实例A、phpMyAdmin查看实例B的情况。
验证方法:在query.php中新增两行代码输出实例标识:
再在phpMyAdmin的SQL窗口执行同样的查询语句echo "MySQL Server ID: " . $conn->query("SELECT @@server_id")->fetch_row()[0]."<br>"; echo "MySQL Port: " . $conn->query("SELECT @@port")->fetch_row()[0]."<br>";SELECT @@server_id, @@port;,如果两个输出不一致即可确认该问题,修正phpMyAdmin的连接配置即可。 - 排查phpMyAdmin的过滤/权限配置
如果确认是同一个实例,可按以下步骤排查:- 直接在phpMyAdmin的SQL窗口执行和
query.php完全一致的查询语句:SELECT * FROM example where id > (SELECT MAX(id) - 20 FROM example),如果能查到数据,说明是表浏览界面的配置问题:要么是无意中设置了时间、ID范围的过滤条件,要么是分页没有停留在第一页,要么是排序字段并非你以为的timestamp字段。 - 如果执行上述SQL还是查不到,检查phpMyAdmin登录的数据库账号权限,确认该账号是否被配置了行级权限,限制只能查看指定时间之前的数据。
- 直接在phpMyAdmin的SQL窗口执行和
- 排查事务提交配置
PDO连接默认开启自动提交,但如果你的MySQL全局配置或者用户级配置关闭了自动提交,也会出现写入的事务只有当前连接可见的问题,可在data_post.php的PDO初始化代码后显式开启自动提交并手动提交事务:$pdo = new PDO("mysql:host=$server;dbname=$database", $user, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 1); // 执行插入操作后新增 $pdo->commit();
内容的提问来源于stack exchange,提问作者marciokoko
相关产品推荐
相关产品推荐

