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.sockhoặ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ớ
localhostvà127.0.0.1khô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.1là 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.

