MySQL:Prepared Statement 预处理语句
预处理语句(Prepared Statements)是 MySQL 中一种用于执行 SQL 查询的高效、安全的方法。通过使用预处理语句,可以显著提升查询性能,并防止 SQL 注入攻击。本文将详细介绍 MySQL 预处理语句的概念、使用方法及其优势。
一、预处理语句概述
预处理语句是一种预编译的 SQL 语句,包含 SQL 语句模板和绑定参数。预处理语句的执行过程分为两步:
- 预编译 SQL 语句:服务器对 SQL 语句进行语法检查,并生成执行计划。
- 执行预处理语句:将参数值绑定到预编译的 SQL 语句中并执行。
二、使用预处理语句
1. 准备环境
首先,我们需要一个测试用的数据库表。例如,我们创建一个名为 employees 的表:
CREATE TABLE employees (
emp_id INT AUTO_INCREMENT PRIMARY KEY,
emp_name VARCHAR(100),
dept_id INT,
salary DECIMAL(10, 2)
);
INSERT INTO employees (emp_name, dept_id, salary) VALUES
('Alice', 1, 5000.00),
('Bob', 2, 6000.00),
('Charlie', 1, 5500.00),
('David', 3, 7000.00),
('Eve', 2, 6500.00);
2. 预处理语句的基本使用
预处理语句主要包括三个步骤:准备、执行和关闭。
准备预处理语句:
PREPARE stmt_name FROM 'SQL语句';
绑定参数并执行预处理语句:
EXECUTE stmt_name USING @param1, @param2, ...;
关闭预处理语句:
DEALLOCATE PREPARE stmt_name;
3. 示例
我们使用预处理语句来查询部门 ID 为 1 的员工信息:
-- 准备预处理语句
PREPARE stmt FROM 'SELECT emp_id, emp_name, salary FROM employees WHERE dept_id = ?';
-- 设置参数
SET @dept_id = 1;
-- 执行预处理语句
EXECUTE stmt USING @dept_id;
-- 关闭预处理语句
DEALLOCATE PREPARE stmt;
三、预处理语句的优势
1. 提升性能
预处理语句通过预编译 SQL 语句,避免了每次执行 SQL 语句时都进行解析和编译,从而提升了查询性能,特别是在需要多次执行相同 SQL 语句的场景中。
2. 防止 SQL 注入
预处理语句将参数绑定与 SQL 语句分离,避免了将用户输入直接插入到 SQL 语句中,从而有效防止了 SQL 注入攻击。
四、高级用法
1. 使用多个参数
预处理语句可以使用多个参数。以下示例演示了如何使用多个参数:
-- 准备预处理语句
PREPARE stmt FROM 'SELECT emp_id, emp_name, salary FROM employees WHERE dept_id = ? AND salary > ?';
-- 设置参数
SET @dept_id = 2;
SET @min_salary = 6000;
-- 执行预处理语句
EXECUTE stmt USING @dept_id, @min_salary;
-- 关闭预处理语句
DEALLOCATE PREPARE stmt;
2. 在存储过程中使用预处理语句
预处理语句也可以在存储过程中使用。以下是一个示例存储过程:
DELIMITER $$
CREATE PROCEDURE GetEmployeesByDept(IN dept_id INT)
BEGIN
PREPARE stmt FROM 'SELECT emp_id, emp_name, salary FROM employees WHERE dept_id = ?';
EXECUTE stmt USING dept_id;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
-- 调用存储过程
CALL GetEmployeesByDept(1);
五、思维导图
MySQL 预处理语句
│
├── 概述
│ ├── 定义
│ ├── 执行过程
│
├── 使用方法
│ ├── 准备环境
│ ├── 基本使用
│ └── 示例
│ └── 查询部门ID为1的员工信息
│
├── 优势
│ ├── 提升性能
│ └── 防止SQL注入
│
├── 高级用法
│ ├── 使用多个参数
│ └── 在存储过程中使用预处理语句### Linux:守护进程(进程组、会话和守护进程)
守护进程(Daemon)是 Linux 系统中一种长期运行的后台进程,通常用于执行系统级别的任务或服务。理解守护进程涉及进程组、会话及其与其他进程的关系。本文将详细介绍这些概念及其在 Linux 中的应用。
#### 一、进程组(Process Group)
进程组是一个或多个进程的集合,用于信号传递和终端输入输出控制。进程组中的每个进程都有一个相同的进程组 ID(PGID),PGID 等于进程组组长的进程 ID(PID)。
##### 1. 创建进程组
当一个进程创建新进程时,默认情况下新进程继承其父进程的 PGID。可以通过调用 `setpgid` 函数来改变进程的 PGID。
include
include
int main() {
pid_t pid = fork();
if (pid == 0) {
// 子进程
setpgid(0, 0); // 创建新的进程组
printf("Child process PGID: %d\n", getpgid(0));
} else {
// 父进程
printf("Parent process PGID: %d\n", getpgid(0));
}
return 0;
}
##### 2. 查看进程组
可以使用 `ps` 命令查看进程的 PGID:
ps -o pid,pgid,cmd
#### 二、会话(Session)
会话是一个或多个进程组的集合。会话由一个会话首领进程创建,该进程成为会话的领导者,并且它的 PID 就是会话 ID(SID)。会话首领进程可以通过调用 `setsid` 函数创建一个新的会话。
##### 1. 创建会话
创建一个新的会话,将当前进程变为会话领导者:
include
include
int main() {
pid_t sid = setsid(); // 创建新的会话
if (sid == -1) {
perror("setsid");
return 1;
}
printf("Session ID: %d\n", sid);
return 0;
}
##### 2. 查看会话
可以使用 `ps` 命令查看进程的 SID:
ps -o pid,sid,cmd
#### 三、守护进程(Daemon)
守护进程是一种在后台运行的进程,通常由系统启动脚本或其他服务管理工具启动。守护进程脱离控制终端,独立于用户的会话。
##### 1. 创建守护进程
创建守护进程的一般步骤包括:
1. **创建子进程,终止父进程**:确保守护进程不是会话领导者,防止它重新打开控制终端。
1. **创建新的会话**:使守护进程成为新会话的领导者。
1. **改变工作目录**:通常将工作目录更改为根目录,以防止锁定任何挂载的文件系统。
1. **重设文件权限掩码**:防止继承父进程的文件权限。
1. **关闭文件描述符**:关闭继承的文件描述符。
下面是一个创建守护进程的示例代码:
include
include
include
include
include
void daemonize() {
pid_t pid;
// 创建子进程
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
if (pid > 0) {
exit(EXIT_SUCCESS); // 父进程退出
}
// 创建新的会话
if (setsid() < 0) {
exit(EXIT_FAILURE);
}
// 捕获、忽略 SIGHUP 信号
signal(SIGHUP, SIG_IGN);
// 创建新子进程,终止父进程,防止重新获得控制终端
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
if (pid > 0) {
exit(EXIT_SUCCESS);
}
// 改变工作目录
if (chdir("/") < 0) {
exit(EXIT_FAILURE);
}
// 重设文件权限掩码
umask(0);
// 关闭文件描述符
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
int main() {
daemonize();
// 守护进程的主循环
while (1) {
// 执行后台任务
sleep(30); // 示例:每隔30秒执行一次任务
}
return EXIT_SUCCESS;
}
#### 四、管理守护进程
##### 1. 使用 `systemd`
现代 Linux 系统通常使用 `systemd` 管理守护进程。可以创建一个 `systemd` 服务文件来管理守护进程。
创建一个示例服务文件 `/etc/systemd/system/mydaemon.service`:
[Unit]
Description=My Daemon Service
[Service]
ExecStart=/usr/local/bin/mydaemon
Restart=always
User=nobody
Group=nobody
[Install]
WantedBy=multi-user.target
然后启用并启动服务:
sudo systemctl enable mydaemon
sudo systemctl start mydaemon
##### 2. 使用 `init.d`
在旧版 Linux 系统中,可以使用 `init.d` 脚本管理守护进程。创建一个示例脚本 `/etc/init.d/mydaemon`:
!/bin/sh
BEGIN INIT INFO
Provides: mydaemon
Required-Start: $remote_fs $syslog
Required-Stop: $remote_fs $syslog
Default-Start: 2 3 4 5
Default-Stop: 0 1 6
Short-Description: My Daemon Service
END INIT INFO
case "$1" in
start)
echo "Starting mydaemon"
/usr/local/bin/mydaemon &
;;
stop)
echo "Stopping mydaemon"
pkill mydaemon
;;
restart)
$0 stop
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0
然后启用并启动服务:
sudo chmod +x /etc/init.d/mydaemon
sudo update-rc.d mydaemon defaults
sudo service mydaemon start
#### 五、思维导图
Linux 守护进程
│
├── 进程组
│ ├── 定义:进程集合
│ ├── 创建:fork + setpgid
│ ├── 查看:ps -o pid,pgid,cmd
│
├── 会话
│ ├── 定义:进程组集合
│ ├── 创建:setsid
│ ├── 查看:ps -o pid,sid,cmd
│
├── 守护进程
│ ├── 定义:后台长期运行进程
│ ├── 创建步骤
│ │ ├── 创建子进程,终止父进程
│ │ ├── 创建新会话
│ │ ├── 改变工作目录
│ │ ├── 重设文件权限掩码
│ │ └── 关闭文件描述符
│ └── 示例代码
│
└── 管理守护进程
├── 使用 systemd
│ ├── 服务文件示例
│ └── 启用和启动服务
└── 使用 init.d
├── 脚本示例
└── 启用和启动服务
#### 六、总结
守护进程在 Linux 系统中扮演着重要角色,通过后台执行关键任务和服务,确保系统的稳定运行。理解进程组和会话的概念,是正确创建和管理守护进程的基础。使用现代的 `systemd` 或传统的 `init.d` 方法,可以有效地管理守护进程,提升系统的可靠性和可维护性。希望本文能帮助读者深入理解并掌握 Linux 守护进程的相关知识。
[
](https://www.tsyvps.com/)
│
└── 思维导图
六、总结
MySQL 预处理语句是一种高效、安全的执行 SQL 查询的方法。通过预编译 SQL 语句,可以显著提升查询性能,并有效防止 SQL 注入攻击。掌握预处理语句的使用方法,对于优化数据库操作和提高应用程序的安全性具有重要意义。希望本文能帮助你更好地理解和使用 MySQL 预处理语句。