Sửa lỗi PHP Warning: mysqli_connect(): (HY000/2002): No such file or directory Khi Dùng localhost

beginner🐘 PHP2026-05-04| Linux (Ubuntu/Debian/CentOS), PHP 7.x/8.x, MySQL 5.7+/MariaDB 10.x, Apache/Nginx

Error Message

Warning: mysqli_connect(): (HY000/2002): No such file or directory
#php#mysqli#mysql#socket#localhost#database

Chuyện Gì Đang Xảy Ra

MySQL đang chạy. PHP đã được cài. Chuỗi kết nối trông ổn. Rồi script của bạn chạy và bạn nhận được lỗi này:

Warning: mysqli_connect(): (HY000/2002): No such file or directory

"File hoặc thư mục" mà PHP không tìm thấy không phải script PHP hay file config của bạn. Đó là một file Unix socket — kênh giao tiếp mà MySQL sử dụng khi bạn kết nối qua localhost.

Có một điều hay khiến mọi người nhầm lẫn: truyền localhost vào mysqli_connect() không dùng TCP/IP. PHP bỏ qua hoàn toàn network stack và tìm kiếm một Unix domain socket trên filesystem. Nếu PHP tìm socket tại /tmp/mysql.sock nhưng MySQL lại đặt nó ở /var/run/mysqld/mysqld.sock, bạn sẽ gặp lỗi này mỗi lần.

Debug: Tìm Vị Trí Thực Sự Của Socket

Bắt đầu bằng cách xác nhận MySQL đang chạy:

sudo systemctl status mysql
# hoặc với MariaDB:
sudo systemctl status mariadb

Không chạy? Khởi động nó là xong. Vẫn đang chạy? Sự không khớp đường dẫn socket mới là thủ phạm. Tìm vị trí socket thực sự:

mysql -u root -p -e "SHOW VARIABLES LIKE 'socket';"

Ví dụ output:

+---------------+--------------------------+
| Variable_name | Value                    |
+---------------+--------------------------+
| socket        | /var/run/mysqld/mysqld.sock |
+---------------+--------------------------+

Giờ kiểm tra PHP đang nghĩ đường dẫn socket là gì:

php -r "echo ini_get('mysqli.default_socket');"

Hoặc tìm trực tiếp trong php.ini:

grep -r "mysqli.default_socket" /etc/php/

Đường dẫn khác nhau? Đó là vấn đề của bạn. Đường dẫn giống nhau nhưng file socket không tồn tại trên ổ đĩa? MySQL không chạy, hoặc nó bị crash khi khởi động.

Giải Pháp 1: Dùng 127.0.0.1 Thay Vì localhost (Nhanh Nhất)

Thay localhost bằng 127.0.0.1. Không cần thay đổi config, không cần restart — chỉ một ký tự khác biệt nhưng thay đổi hoàn toàn cách PHP kết nối:

<?php
// Trước (dùng Unix socket — bị lỗi nếu đường dẫn socket sai)
$conn = mysqli_connect('localhost', 'myuser', 'mypass', 'mydb');

// Sau (bắt buộc dùng TCP/IP — bỏ qua hoàn toàn vấn đề socket)
$conn = mysqli_connect('127.0.0.1', 'myuser', 'mypass', 'mydb');
?>

Với 127.0.0.1, PHP kết nối qua TCP trên cổng 3306. MySQL lắng nghe ở đó theo mặc định, vì vậy cách này hoạt động ngay lập tức trên hầu hết các thiết lập.

Dùng PDO? Thay tương tự:

<?php
$pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=mydb', 'myuser', 'mypass');
?>

Giải Pháp 2: Sửa Đường Dẫn Socket Trong php.ini (Cách Đúng Đắn)

Nếu bạn không thể thay đổi code kết nối — chẳng hạn đó là ứng dụng legacy hoặc CMS bạn không kiểm soát — hãy căn chỉnh thiết lập socket của PHP với vị trí MySQL thực sự đặt nó.

Trước tiên, tìm php.ini đang hoạt động:

php --ini | grep "Loaded Configuration"

Mở file đó và cập nhật tất cả ba thiết lập socket để khớp với đường dẫn từ SHOW VARIABLES LIKE 'socket':

; Trong php.ini
mysqli.default_socket = /var/run/mysqld/mysqld.sock
pdo_mysql.default_socket = /var/run/mysqld/mysqld.sock
mysql.default_socket = /var/run/mysqld/mysqld.sock

Sau đó restart tiến trình PHP của bạn:

# Với PHP-FPM:
sudo systemctl restart php8.1-fpm

# Với Apache dùng mod_php:
sudo systemctl restart apache2

Giải Pháp 3: Truyền Socket Trực Tiếp Trong Code

Thay vì dựa vào các giá trị mặc định trong php.ini, hãy hardcode đường dẫn socket trực tiếp trong mysqli_connect(). Hữu ích khi bạn cần một kết nối dùng socket còn các kết nối khác dùng TCP:

<?php
$conn = mysqli_connect(
    'localhost',
    'myuser',
    'mypass',
    'mydb',
    3306,
    '/var/run/mysqld/mysqld.sock'  // đường dẫn socket tường minh
);
?>

Kiểu OOP:

<?php
$mysqli = new mysqli();
$mysqli->real_connect(
    'localhost',
    'myuser',
    'mypass',
    'mydb',
    3306,
    '/var/run/mysqld/mysqld.sock'
);
?>

Đường Dẫn Socket Phổ Biến Theo Hệ Thống

Vị trí socket thay đổi tùy theo distro và phiên bản MySQL. Đây là nơi cần tìm:

  • Ubuntu/Debian (MySQL): /var/run/mysqld/mysqld.sock
  • CentOS/RHEL (MySQL): /var/lib/mysql/mysql.sock
  • MariaDB (hầu hết distro): /var/run/mysqld/mysqld.sock hoặc /tmp/mysql.sock
  • MAMP/XAMPP (macOS): /Applications/MAMP/tmp/mysql/mysql.sock
  • Homebrew MySQL (macOS): /tmp/mysql.sock

Khi không chắc, hãy chạy SHOW VARIABLES LIKE 'socket' — MySQL luôn biết nó đã đặt file ở đâu.

Kiểm Tra Kết Quả

Kiểm tra từ command line trước khi động vào ứng dụng:

php -r "
\$conn = mysqli_connect('127.0.0.1', 'myuser', 'mypass', 'mydb');
if (\$conn) {
    echo 'Connected successfully\n';
    mysqli_close(\$conn);
} else {
    echo 'Error: ' . mysqli_connect_error() . '\n';
}
"

Hoặc thêm đoạn tạm thời này vào ứng dụng để xem phiên bản server khi kết nối thành công:

<?php
$conn = mysqli_connect('127.0.0.1', 'myuser', 'mypass', 'mydb');
if (!$conn) {
    die('Connection failed: ' . mysqli_connect_error());
}
echo 'Connected. MySQL server version: ' . mysqli_get_server_info($conn);
mysqli_close($conn);
?>

Những Điểm Cần Nhớ

  • localhost127.0.0.1 không thể hoán đổi cho nhau trong các kết nối database PHP. Một cái kết nối qua file Unix socket; cái còn lại đi qua TCP/IP.
  • "No such file or directory" là lỗi filesystem, không phải lỗi mạng. PHP thực sự không tìm thấy file socket tại đường dẫn nó mong đợi.
  • Chuyển đổi giữa MySQL và MariaDB, hoặc di chuyển giữa các distro, thường thay đổi đường dẫn socket. Luôn kiểm tra lại.
  • Trong Docker container hoặc môi trường hỗn hợp nơi đường dẫn socket thay đổi, 127.0.0.1 là lựa chọn linh hoạt hơn — nó không phụ thuộc vào bất kỳ file nào tồn tại trên ổ đĩa.

Related Error Notes