PHP报错Call to undefined function解决
前言
运行PHP代码,突然报错:"Call to undefined function xxx()"?这个错太常见了,一般就是扩展没装或者文件没引入。本文讲怎么排查和解决。
一、报错长啥样
Fatal error: Uncaught Error: Call to undefined function mysql_connect() in xxx.php on line 5
意思:你调用了一个不存在的函数。
二、常见原因
原因1:PHP扩展没装
比如用了 mysqli_connect(),但没装mysqli扩展。
或者用了 gd库 的函数,但没装gd。
原因2:文件没引入
你自己写的函数,忘了include/require文件。
原因3:函数名写错了
拼写错了,比如 str_lower 写成 strlower。
原因4:PHP版本不对
低版本PHP没有高版本才有的函数。
三、排查步骤
第一步:看是哪个函数报错
报错信息里会告诉你函数名:
Call to undefined function curl_init()
这里就是 curl_init() 函数没找到。
第二步:判断是内置函数还是自己写的
- 内置函数:PHP自带的,比如
curl_init、mysqli_connect - 自己写的:你在别的文件里定义的
第三步:如果是内置函数,查扩展装了没
php -m | grep curl
看看curl扩展装了没。
或者写个phpinfo:
<?php
phpinfo();
?>
搜这个函数名对应的扩展,看有没有。
四、安装扩展
例子1:装curl扩展
# CentOS
yum install php-curl
# Ubuntu
apt install php-curl
例子2:装mysqli扩展
yum install php-mysqli
例子3:装gd库
yum install php-gd
装完重启
systemctl restart php-fpm
五、如果是自己写的函数
检查文件引入
<?php
// 引入函数文件
require 'functions.php';
// 调用
my_function();
检查函数名对不对
// functions.php里定义的
function my_function() {
// ...
}
调用的时候名字要一模一样。
检查命名空间
如果用了命名空间,要注意:
<?php
namespace App;
// 调用别的命名空间的函数
\OtherNamespace\my_function();
六、常见函数和对应扩展
| 函数 | 需要的扩展 |
|---|---|
| mysqli_connect | mysqli |
| curl_init | curl |
| imagecreate | gd |
| mb_strlen | mbstring |
| openssl_encrypt | openssl |
| pdo连接 | pdo_mysql |
| json_encode | json(默认有) |
| file_get_contents | 不需要(默认有) |
七、常见坑
坑1:mysql函数被废弃了
PHP7以后,mysql_* 函数都没了,要用mysqli或者PDO。
Call to undefined function mysql_connect()
解决: 换成mysqli或者PDO。
坑2:CLI和FPM装的扩展不一样
命令行里装了,网页上没有。
原因: CLI和FPM用不同的php.ini。
解决: 看phpinfo里的配置,装到对应的PHP版本里。
坑3:装了扩展没重启
装完忘了重启php-fpm。
解决:
systemctl restart php-fpm
坑4:函数名大小写
PHP函数名不区分大小写,但自己写的类方法区分。
坑5:Composer自动加载没生效
用了Composer的库,但没 vendor/autoload.php。
require 'vendor/autoload.php';
八、快速排查
第一步:看报错的函数名
Call to undefined function xxx()
第二步:查扩展
php -m | grep 扩展名
第三步:没装就装
yum install php-扩展名
第四步:重启
systemctl restart php-fpm
九、常用扩展安装
一次性装常用扩展
yum install php-mysqli php-curl php-gd php-mbstring php-xml php-json
Ubuntu
apt install php-mysqli php-curl php-gd php-mbstring php-xml
总结
记住:
- 报错会告诉你是哪个函数没找到
- 内置函数就查扩展装了没
- 自己写的就查文件引入了没
- 装完扩展要重启php-fpm
- mysql_* 函数PHP7没了,换mysqli
排查流程:
看报错函数名 → 判断是内置还是自己写的 → 内置查扩展 → 自己写的查引入 → 解决
遇到问题加QQ23979811 协助处理
MySQL报错"Too many connections"解决
前言
网站突然打不开,MySQL报"Too many connections",连接数满了。本文讲怎么排查和解决。
报错长什么样
ERROR 1040 (00000): Too many connections
意思是MySQL连接数超过最大限制了。
一、先紧急处理
查看当前连接数
SHOW STATUS LIKE 'Threads_connected';
查看最大连接数
SHOW VARIABLES LIKE 'max_connections';
默认一般是151或者100。
临时调大连接数
SET GLOBAL max_connections = 1000;
马上生效,不用重启。
二、查看谁占了连接
查看所有连接
SHOW FULL PROCESSLIST;
按用户统计
SELECT user, COUNT(*) FROM information_schema.processlist GROUP BY user;
按IP统计
SELECT SUBSTRING_INDEX(host, ':', 1) AS ip, COUNT(*)
FROM information_schema.processlist
GROUP BY ip;
杀掉多余连接
-- 杀掉Sleep的连接
KILL 连接ID;
批量杀:
SELECT CONCAT('KILL ', id, ';') FROM information_schema.processlist
WHERE user = 'www' AND command = 'Sleep';
三、永久修改最大连接数
改my.cnf:
[mysqld]
max_connections = 1000
重启MySQL:
systemctl restart mysqld
四、为什么连接数会满
原因1:程序没关连接
每查一次数据库就新开一个连接,用完不关,连接越积越多。
解决:
- 用连接池
- 用完及时关连接
原因2:慢SQL占着连接
一条SQL跑10秒,请求一多,连接就占满了。
解决: 优化慢SQL,加快查询速度。
原因3:max_connections太小
默认151,大流量网站不够用。
解决: 调大到500或1000。
原因4:Sleep连接太多
大量空闲连接占着位置。
解决: 调小wait_timeout:
[mysqld]
wait_timeout = 60
interactive_timeout = 60
空闲60秒自动断开。
五、排查步骤
第一步:确认是不是真的满了
SHOW STATUS LIKE 'Threads_connected';
SHOW VARIABLES LIKE 'max_connections';
第二步:看谁占了连接
SHOW FULL PROCESSLIST;
第三步:找原因
是慢SQL?还是程序泄漏?还是连接数太小?
第四步:紧急处理
SET GLOBAL max_connections = 1000;
或者杀掉Sleep连接。
常见坑
坑1:改了配置不生效
改了my.cnf,重启了,还是151。
原因: 改错配置文件了。
解决: 确认MySQL读的是哪个配置文件:
mysql --help | grep my.cnf
坑2:max_connections调太大
调到10000,结果MySQL启动不了。
原因: 每个连接都要占内存,太多会把内存吃满。
解决: 一般500-1000够用了,别调太大。
坑3:连接泄漏没解决
调大了max_connections,过几天又满了。
原因: 程序有连接泄漏,没根本解决。
解决: 查代码,修连接泄漏问题。
坑4:max_user_connections限制
单个用户连接数也有限制。
查看:
SHOW VARIABLES LIKE 'max_user_connections';
总结
紧急处理三步:
SHOW FULL PROCESSLIST看谁占连接- 杀掉多余连接
- 调大
max_connections
根本解决: 优化慢SQL + 修连接泄漏 + 用连接池。
遇到问题加QQ23979811 协助处理
MySQL报错"Table 'xxx' doesn't exist"解决
前言
查询数据库时报错:Table 'xxx' doesn't exist,明明表就在那,为什么说不存在?本文排查常见原因。
报错长什么样
SELECT * FROM users;
报错:
ERROR 1146 (42S02): Table 'mydb.users' doesn't exist
常见原因
原因1:数据库选错了
当前在别的库里,所以找不到表。
排查: 先看当前在哪个库:
SELECT DATABASE();
如果显示的不是你要的库,就切换:
USE mydb;
再查一次。
原因2:表名写错了
拼错了,或者大小写不对。
排查: 看看库里到底有哪些表:
SHOW TABLES;
确认表名是不是和你写的一模一样。
注意: Linux下MySQL表名区分大小写,Users 和 users 是两个表。
原因3:表真的被删了
表确实不存在了,可能被误删了。
排查: 用SHOW TABLES确认。如果真没有,从备份恢复。
原因4:字符集导致的问题
表名里有特殊字符,编码不对导致识别不出来。
排查: 用 SHOW TABLES LIKE 'xxx%'; 模糊匹配一下。
原因5:MySQL升级后表损坏
升级MySQL后,某些表报错不存在,但文件还在。
原因: 表引擎损坏,或者frm文件丢了。
排查: 看数据目录下有没有对应文件:
ls /var/lib/mysql/mydb/
原因6:用户没有权限
虽然报错是"不存在",但有时候权限不够也会这么报。
排查: 用root用户登录试试,如果root能看到,就是权限问题。
排查步骤
第一步:确认当前数据库
SELECT DATABASE();
第二步:查看所有表
SHOW TABLES;
第三步:模糊搜索表名
SHOW TABLES LIKE '%user%';
第四步:确认表文件是否存在
ls /var/lib/mysql/你的库名/ | grep 表名
常见坑
坑1:Linux下表名区分大小写
Windows开发没问题,上传到Linux服务器就报错。
解决: 表名统一用小写,或者在my.cnf加:
lower_case_table_names = 1
注意: 这个参数只能在初始化MySQL前设置,已经用了再改会出问题。
坑2:分表了忘了加表名
用了分表,代码里查的是 users,实际表名是 users_0、users_1。
解决: 确认分表规则,代码里拼对表名。
坑3:视图报错
查视图时报"表不存在",可能是视图依赖的表被删了。
排查: 看视图定义:
SHOW CREATE VIEW 视图名;
坑4:临时表
会话结束临时表就没了,新开一个连接查就报错。
解决: 临时表只在当前会话有效,别跨连接用。
坑5:误删了库
整个库都没了,当然找不到表。
排查:
SHOW DATABASES;
看你的库还在不在。
总结
排查顺序:
- 先看当前在哪个库
- 再SHOW TABLES看表在不在
- 确认表名大小写对不对
- 最后看数据目录下文件在不在
记住: 90%的情况都是库选错了或者表名写错了。
遇到问题加QQ23979811 协助处理
MySQL数据库导入sql文件报错解决
前言
导入SQL文件到MySQL,经常报各种错。本文总结最常见的导入报错和解决方法。
常用导入命令
mysql -u root -p 数据库名 < xxx.sql
或者登录MySQL后:
source /路径/xxx.sql;
常见报错及解决
报错1:Unknown database
ERROR 1049 (42000): Unknown database 'xxx'
原因: 数据库不存在。
解决: 先创建数据库:
CREATE DATABASE xxx DEFAULT CHARSET utf8mb4;
然后再导入。
报错2:Access denied
ERROR 1044 (42000): Access denied for user
原因: 用户没权限。
解决: 用root用户导入,或者给用户授权。
报错3:File not found
ERROR 1045 (28000): Access denied
或者文件找不到。
原因: 文件路径不对,或者文件权限不对。
解决:
- 确认文件存在:
ls -l /路径/xxx.sql - 确认文件可读:
chmod 644 /路径/xxx.sql - 用绝对路径,别用相对路径
报错4:Table already exists
ERROR 1050 (42S01): Table 'xxx' already exists
原因: 表已经存在了。
解决: 两种方法:
- 先删表再导入:
DROP TABLE xxx; - SQL文件里加
DROP TABLE IF EXISTS xxx;
报错5:Duplicate entry
ERROR 1062 (23000): Duplicate entry 'xxx' for key
原因: 主键重复。
解决:
- 先清空表再导入
- 或者用
INSERT IGNORE跳过重复
报错6:字符集乱码
导入后中文变成乱码。
原因: 字符集不对。
解决: 导入前设置字符集:
SET NAMES utf8mb4;
source /路径/xxx.sql;
或者命令行指定:
mysql -u root -p --default-character-set=utf8mb4 数据库名 < xxx.sql
报错7:max_allowed_packet太小
ERROR 2006 (HY000): MySQL server has gone away
原因: SQL文件太大,MySQL接收不了。
解决: 修改my.cnf,加大max_allowed_packet:
[mysqld]
max_allowed_packet = 64M
重启MySQL生效。
导入大文件技巧
方法1:分卷压缩
把大SQL文件拆成小的:
split -b 10M xxx.sql small_
然后逐个导入。
方法2:跳过外键检查
导入时临时关闭外键检查,更快:
SET FOREIGN_KEY_CHECKS = 0;
source /路径/xxx.sql;
SET FOREIGN_KEY_CHECKS = 1;
常见坑
坑1:用错用户名密码
导入时一直提示密码错误。
解决: 确认用户名密码,或者用 mysql -u root -p 交互式输入密码。
坑2:SQL文件不是UTF-8编码
导入后中文乱码。
解决: 用 file 命令查看文件编码:
file -i xxx.sql
坑3:没选对数据库
导入后数据不知道导到哪去了。
解决: 命令行一定要指定数据库名,或者先 USE 数据库名;
总结
导入SQL文件三步走:
- 先确认数据库存在
- 用正确的字符集导入
- 大文件就调大max_allowed_packet
记住: 报错信息一定要看清楚,别瞎试。
遇到问题加QQ23979811 协助处理
MySQL数据库导入sql文件报错解决
前言
做网站开发或者运维的同学肯定经常遇到这种情况:把本地写好的项目传到服务器上,需要把本地的数据库sql文件导入到服务器的MySQL里。但是导入的时候经常报错,各种问题层出不穷,折腾半天都导不进去。
这篇文章就把MySQL导入sql文件时最常见的报错和解决方法都整理出来,帮你快速搞定导入问题。
常用导入命令
首先先讲一下最常用的导入sql文件的命令:
mysql -u root -p 数据库名 < /路径/你的sql文件.sql
比如你要把 test.sql 导入到 testdb 数据库里,命令就是:
mysql -u root -p testdb < /root/test.sql
执行完之后输入密码,就开始导入了。
常见报错及解决方法
1. 报错:Unknown database 'xxx'
这个报错的意思是你要导入的数据库不存在。很多同学直接就执行导入命令了,结果数据库还没建,肯定报错。
解决方法:
先登录MySQL,创建对应的数据库:
CREATE DATABASE testdb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
创建完数据库之后再执行导入命令。
2. 报错:File 'xxx.sql' not found
这个报错的意思是找不到sql文件。一般是因为你写的文件路径不对。
解决方法:
先确认一下sql文件的实际路径:
pwd
ls -l
确认文件确实在那个路径下,然后用绝对路径来导入,不要用相对路径。
3. 报错:Access denied for user 'root'@'localhost'
这个报错的意思是权限不足,没有权限往这个数据库里导入数据。
解决方法:
确认你登录MySQL用的用户有没有这个数据库的权限。如果是root用户,一般不会有这个问题。如果是其他用户,需要给用户授权:
GRANT ALL PRIVILEGES ON testdb.* TO '用户名'@'localhost';
FLUSH PRIVILEGES;
4. 报错:Packet larger than max_allowed_packet bytes
这个报错一般是因为你的sql文件太大了,超过了MySQL允许的最大数据包大小。
解决方法:
先查看当前的 max_allowed_packet 大小:
SHOW VARIABLES LIKE 'max_allowed_packet';
然后临时调大一点,比如调到100M:
SET GLOBAL max_allowed_packet = 104857600;
或者修改my.cnf配置文件,在 [mysqld] 下面加上:
[mysqld]
max_allowed_packet = 100M
然后重启MySQL服务再导入。
5. 报错:You have an error in your SQL syntax
这个报错的意思是SQL语法错误。一般是因为你的sql文件里有某些SQL语句在当前MySQL版本不兼容。
解决方法:
看看报错信息里说的是哪一行的语法错误,然后打开sql文件找到那一行,把不兼容的语法改一下。
比如从MySQL 8.0导出的sql文件导入到MySQL 5.7里,经常会有一些语法不兼容的问题,需要手动改一下。
6. 导入到一半就卡住了,或者超时了
如果你的sql文件特别大(几百M甚至几个G),导入的时候可能会卡住,或者因为超时而中断。
解决方法:
- 先把 sql_mode 调整一下,去掉一些严格模式:
SET GLOBAL sql_mode = '';
- 关闭自动提交,提升导入速度:
SET autocommit = 0;
- 如果还是太慢,可以考虑用 source 命令导入:
USE testdb;
source /root/test.sql;
7. 中文乱码问题
导入完数据之后发现中文都变成乱码了。这一般是因为字符集不匹配。
解决方法:
导入之前先设置一下字符集:
SET NAMES utf8mb4;
然后再导入数据。或者导入的时候加上 --default-character-set 参数:
mysql -u root -p --default-character-set=utf8mb4 testdb < /root/test.sql
常见坑
坑1:忘记先创建数据库就直接导入
很多同学导入的时候直接就执行命令了,结果数据库还没建,肯定报错。一定要先确认数据库存在,再导入。
坑2:用相对路径导入找不到文件
很多同学写的是 mysql -u root -p testdb < test.sql,结果提示找不到文件。这是因为你当前所在的目录和sql文件所在的目录不一样,相对路径找不到。最好用绝对路径来导入。
坑3:导入完数据之后中文乱码
导入完数据发现中文都变成问号或者乱码了,这一般是字符集的问题。导入的时候一定要指定 utf8mb4 字符集,不然中文很容易乱码。
坑4:大文件导入到一半就中断了
大文件导入的时候很容易因为超时而中断,特别是几百M以上的sql文件。这时候可以调整一下超时时间,或者用 source 命令在MySQL内部导入,会稳定很多。
总结
MySQL导入sql文件的常见报错和解决方法总结一下:
- 数据库不存在 → 先创建数据库
- 文件找不到 → 用绝对路径
- 权限不足 → 给用户授权
- 数据包太大 → 调大 max_allowed_packet
- 语法错误 → 检查SQL语句兼容性
- 导入慢/卡住 → 关闭自动提交,用source命令
- 中文乱码 → 指定utf8mb4字符集
记住这些常见问题和解决方法,以后导入sql文件的时候就不会再手忙脚乱了。
遇到问题加QQ23979811 协助处理