MySQL报“Can't create table”但df -h显示磁盘有空间,根源常是inode耗尽而非字节空间不足;需用df -i检查,大量小文件(如日志、binlog)易导致该问题。

phpEnv 本身不管理 MySQL 存储,MySQL 创建表失败若报 No space left on device,根源在磁盘空间或 inode 耗尽,与 phpEnv 无关 —— 但你可以用它快速切换 PHP 环境来执行诊断脚本。
为什么 MySQL 报错“Can't create table”却显示磁盘还有空间
常见于 MySQL 数据目录(如 /var/lib/mysql 或 ~/.phpenv/versions/*/share/mysql)所在分区的 inode 耗尽,而非字节空间不足。此时 df -h 看起来正常,但 df -i 显示 Use% 达到 100%。
- 大量小文件(如 Laravel 的
storage/logs/*.log、WordPress 的临时插件缓存、MySQL 的 binlog 或临时表)会快速吃光 inode - phpEnv 安装的 MySQL 实例默认数据目录通常在用户家目录下(如
~/.phpenv/versions/8.3.13/share/mysql),需检查该路径所在挂载点 - MySQL 创建表时需写入
.frm、.ibd等多个文件,任一环节因 inode 不足失败,就会抛出该错误
用 PHP 快速检查 MySQL 数据目录所在分区的磁盘与 inode 使用率
在 phpEnv 激活的 PHP 版本下,直接运行以下脚本(替换 $mysql_data_dir 为你的实际路径):
```php
$mysql_data_dir = '/var/lib/mysql'; // 或 ~/.phpenv/versions/8.3.13/share/mysql
$realpath = realpath($mysql_data_dir);
<p>if (!$realpath || !is_dir($realpath)) {
echo "MySQL data dir not found or inaccessible\n";
exit(1);
}</p><p>// 获取所在挂载点(Linux)
$mount_point = trim(shell_exec("df --output=source '$realpath' 2>/dev/null | tail -1"));
if (!$mount_point) {
$mount_point = trim(shell_exec("df '$realpath' 2>/dev/null | tail -1 | awk '{print \$1}'"));
}</p><p>echo "Mount point: $mount_point\n";
echo "Disk usage: " . round((disk_total_space($realpath) - disk_free_space($realpath)) / disk_total_space($realpath) * 100, 1) . "%\n";</p><p>// inode 使用率需调用 df -i(PHP 无原生函数)
$inode_out = shell_exec("df -i '$realpath' 2>/dev/null | tail -1");
if ($inode_out) {
$parts = preg_split('/\s+/', trim($inode_out));
if (count($parts) >= 5) {
echo "Inode usage: {$parts[4]}\n";
}
}</p><pre class='brush:</pre>;toolbar:false;'>
<ul>
<li>务必用 <code>realpath()</code> 解析符号链接,避免误判挂载点</li>
<li><code>disk_total_space()</code> 和 <code>disk_free_space()</code> 只反映字节空间,对 inode 无效 —— 必须调用 <code>df -i</code></li>
<li>若 <code>$mysql_data_dir</code> 在非 root 用户目录下(如 phpEnv 自带 MySQL),注意检查当前 PHP 进程是否有权限读取该路径</li>
</ul>
<H3>排查 phpEnv 下 MySQL 实际数据目录位置</H3>
<p>phpEnv 不自带 MySQL;你大概率是用系统 MySQL 或手动部署了 MariaDB/MySQL 实例。确认真实数据目录:</p>
<ul>
<li>进 MySQL 执行:<code>SHOW VARIABLES LIKE 'datadir';</code></li>
<li>查 MySQL 配置文件:<code>mysqld --help --verbose 2>/dev/null | grep "datadir"</code> 或检查 <code>/etc/mysql/my.cnf</code>、<code>~/.my.cnf</code></li>
<li>若用 phpEnv + docker 组合,数据目录可能映射到宿主机某路径,需检查 <code>docker inspect</code> 中的 <code>Mounts</code> 字段</li>
<li>别直接信任 <code>which mysql</code> 输出 —— 它只告诉你客户端位置,不是服务端数据目录</li>
</ul>
<p>真正卡住的地方,往往不是「磁盘满」,而是「inode 满」或「MySQL 数据目录被挂载在独立小分区上」。用 <code>df -i</code> 和 <code>find /path/to/datadir -type f | wc -l</code> 两行命令,比翻日志快十倍。</p>



















