LNMP架构(分离部署)PHP与数据库交互示例
基于你的三台服务器地址:
- 数据库服务器(MySQL):192.168.100.10
- Nginx服务器:192.168.100.20
- PHP服务器:192.168.100.30
下面将通过一个"用户信息查询"的简单例子,展示如何实现跨服务器的PHP与数据库交互。
一、数据库服务器(192.168.100.10)配置
1. 登录MySQL并创建测试数据
bash
# 登录MySQL
mysql -uroot -predhat
执行以下SQL语句:
sql
-- 创建测试数据库
CREATE DATABASE IF NOT EXISTS demo_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建专门用于PHP连接的用户(仅允许从PHP服务器IP连接)
CREATE USER 'root'@'192.168.100.30' IDENTIFIED BY 'redhat';
GRANT SELECT, INSERT, UPDATE ON demo_db.* TO 'root'@'192.168.100.30';
FLUSH PRIVILEGES;
-- 切换到demo_db数据库
USE demo_db;
-- 创建用户表
CREATE TABLE IF NOT EXISTS users (
id INT(11) NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL COMMENT '用户名',
age INT(3) NOT NULL COMMENT '年龄',
email VARCHAR(100) UNIQUE NOT NULL COMMENT '邮箱',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 插入测试数据
INSERT INTO users (name, age, email) VALUES
('张三', 25, 'zhangsan@example.com'),
('李四', 30, 'lisi@example.com'),
('王五', 28, 'wangwu@example.com');
2. 配置MySQL允许远程连接
bash
# 编辑MySQL配置文件
vim /etc/my.cnf
# 注释掉bind-address(如果存在)
# bind-address = 127.0.0.1
# 重启MySQL
systemctl restart mysqld
# 开放3306端口
firewall-cmd --zone=public --add-port=3306/tcp --permanent
firewall-cmd --reload
二、PHP服务器(192.168.100.30)配置
1. 安装PHP MySQL扩展
bash
# 安装PHP MySQL扩展
yum -y install php-mysqlnd php-pdo
# 重启PHP-FPM
systemctl restart php-fpm
# 开放9000端口(PHP-FPM默认端口)
firewall-cmd --zone=public --add-port=9000/tcp --permanent
firewall-cmd --reload
2. 创建PHP测试脚本
bash
# 创建网站根目录
mkdir -p /var/www/html
# 创建测试脚本
vim /var/www/html/user_query.php
脚本内容:
php
<?php
// 数据库连接配置(使用数据库服务器IP)
$dbConfig = [
'host' => '192.168.100.10', // 数据库服务器IP
'dbname' => 'demo_db', // 数据库名
'username' => 'root', // 数据库用户
'password' => 'redhat', // 数据库密码
'port' => 3306 // 数据库端口
];
try {
// 建立数据库连接(PDO方式,推荐)
$dsn = "mysql:host={$dbConfig['host']};dbname={$dbConfig['dbname']};port={$dbConfig['port']};charset=utf8mb4";
$pdo = new PDO(
$dsn,
$dbConfig['username'],
$dbConfig['password'],
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]
);
// 1. 查询所有用户
$stmt = $pdo->query("SELECT * FROM users");
$users = $stmt->fetchAll();
// 2. 插入新用户(演示)
$newUser = [
'name' => '赵六',
'age' => 35,
'email' => 'zhaoliu@example.com'
];
$insertStmt = $pdo->prepare("INSERT INTO users (name, age, email) VALUES (?, ?, ?)");
$insertSuccess = $insertStmt->execute([$newUser['name'], $newUser['age'], $newUser['email']]);
} catch (PDOException $e) {
// 捕获连接或查询错误
die("数据库操作失败:" . $e->getMessage());
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>PHP与MySQL交互示例</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.container { max-width: 800px; margin: 0 auto; }
.user-table { width: 100%; border-collapse: collapse; margin-top: 20px; }
.user-table th, .user-table td { border: 1px solid #ddd; padding: 8px; text-align: left; }
.user-table th { background-color: #f2f2f2; }
.success { color: green; }
.error { color: red; }
</style>
</head>
<body>
<div class="container">
<h1>用户信息列表</h1>
<?php if (isset($insertSuccess) && $insertSuccess): ?>
<p class="success">新用户"<?php echo $newUser['name']; ?>"插入成功!</p>
<?php endif; ?>
<?php if (!empty($users)): ?>
<table class="user-table">
<tr>
<th>ID</th>
<th>姓名</th>
<th>年龄</th>
<th>邮箱</th>
</tr>
<?php foreach ($users as $user): ?>
<tr>
<td><?php echo $user['id']; ?></td>
<td><?php echo $user['name']; ?></td>
<td><?php echo $user['age']; ?></td>
<td><?php echo $user['email']; ?></td>
</tr>
<?php endforeach; ?>
</table>
<?php else: ?>
<p class="error">没有查询到用户数据</p>
<?php endif; ?>
</div>
</body>
</html>
设置文件权限:
bash
# 设置正确权限
chown -R apache:apache /var/www/html # 若PHP-FPM运行用户为apache
# 或 chown -R nginx:nginx /var/www/html # 若PHP-FPM运行用户为nginx
三、Nginx服务器(192.168.100.20)配置
1. 安装Nginx(若未安装)
bash
安装nginx-1.24.0
2. 配置Nginx反向代理到PHP服务器
bash
# 创建站点配置文件
vim /usr/local/nginx/conf/nginx.conf
配置内容:
nginx
server {
listen 80;
server_name localhost; # 可替换为实际域名
# 开放文件上传大小限制
client_max_body_size 10M;
# 所有请求转发到PHP服务器处理
location / {
# 代理到PHP服务器的9000端口(PHP-FPM)
fastcgi_pass 192.168.100.30:9000;
# 设置PHP文件路径(PHP服务器上的实际路径)
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
include fastcgi_params;
# 超时设置
fastcgi_connect_timeout 30s;
fastcgi_send_timeout 30s;
fastcgi_read_timeout 30s;
}
# 日志配置
error_log /var/log/nginx/demo_error.log;
access_log /var/log/nginx/demo_access.log main;
}
3. 重启Nginx并开放端口
bash
# 检查配置是否正确
nginx -t
# 重启Nginx
systemctl restart nginx
# 开放80端口
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload
四、测试效果
在本地电脑的浏览器中访问Nginx服务器地址:
http://192.168.100.20/user_query.php
预期效果:
- 页面会显示数据库中已有的3条用户信息(张三、李四、王五)
- 同时会插入一条新用户"赵六"的记录
- 表格会展示所有用户的ID、姓名、年龄和邮箱信息
验证数据是否真的插入:
在数据库服务器上执行:
bash
mysql -uroot -predhat -e "SELECT * FROM demo_db.users;"
可以看到查询结果中包含"赵六"的记录,说明PHP与数据库交互成功。

五、常见问题排查
-
连接超时:
- 检查数据库服务器3306端口是否开放
- 验证PHP服务器是否能ping通数据库服务器(
ping 192.168.100.10
) - 检查数据库用户是否允许从PHP服务器IP连接(
SELECT user,host FROM mysql.user;
)
-
权限错误:
- 确保PHP脚本文件权限正确
- 检查PHP-FPM运行用户是否有访问脚本的权限
-
Nginx 502错误:
- 检查PHP服务器9000端口是否开放
- 确认PHP-FPM服务是否正常运行(
systemctl status php-fpm
)
-
访问被拒绝,首先查明数据库用户有没有权限访问。
通过这个简单的例子,你可以清晰地看到LNMP分离架构中PHP如何与远程数据库进行交互,包括查询数据和插入数据的基本操作。
r,host FROM mysql.user;`)
-
权限错误:
- 确保PHP脚本文件权限正确
- 检查PHP-FPM运行用户是否有访问脚本的权限
-
Nginx 502错误:
- 检查PHP服务器9000端口是否开放
- 确认PHP-FPM服务是否正常运行(
systemctl status php-fpm
)
-
访问被拒绝,首先查明数据库用户有没有权限访问。
通过这个简单的例子,你可以清晰地看到LNMP分离架构中PHP如何与远程数据库进行交互,包括查询数据和插入数据的基本操作。