MySQL:Prepared Statement 预处理语句

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL 预处理语句是一种高效、安全的执行 SQL 查询的方法。通过预编译 SQL 语句,可以显著提升查询性能,并有效防止 SQL 注入攻击。掌握预处理语句的使用方法,对于优化数据库操作和提高应用程序的安全性具有重要意义。希望本文能帮助你更好地理解和使用 MySQL 预处理语句。

MySQL:Prepared Statement 预处理语句

预处理语句(Prepared Statements)是 MySQL 中一种用于执行 SQL 查询的高效、安全的方法。通过使用预处理语句,可以显著提升查询性能,并防止 SQL 注入攻击。本文将详细介绍 MySQL 预处理语句的概念、使用方法及其优势。

一、预处理语句概述

预处理语句是一种预编译的 SQL 语句,包含 SQL 语句模板和绑定参数。预处理语句的执行过程分为两步:

  1. 预编译 SQL 语句:服务器对 SQL 语句进行语法检查,并生成执行计划。
  2. 执行预处理语句:将参数值绑定到预编译的 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 预处理语句。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
SQL 关系型数据库 MySQL
Go语言中进行MySQL预处理和SQL注入防护
在现代Web应用开发中,安全性至关重要。SQL注入是一种常见的攻击方式,攻击者可通过构造特殊SQL查询来非法访问或修改数据库数据。本文介绍如何利用Go语言中的预处理SQL语句来防范此类攻击。预处理不仅能提升安全性,还能提高性能并简化代码。通过使用`?`作为占位符,Go自动处理参数转义,有效避免SQL注入。此外,文章还提供了连接MySQL数据库、执行预处理查询以及最佳实践的示例代码。务必遵循这些指导原则,确保应用程序的安全性。
411 0
|
SQL 存储 关系型数据库
MySQL - 动态SQL与预处理语句
MySQL - 动态SQL与预处理语句
222 0
|
druid 关系型数据库 MySQL
高并发下 MySQL Statement Cancellation Timer 的线程数暴涨
高并发下 MySQL Statement Cancellation Timer 的线程数暴涨
|
移动开发 JSON 关系型数据库
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
|
SQL 关系型数据库 MySQL
Mysql中varchar字符串的比较,swoole预处理参数绑定
使用的是php swoole,预处理。 解决有两条路:mysql的字段类型改为数字;研究swoole的参数预处理问题,可以测试普通PHP的预处理是否也有问题
227 0
|
关系型数据库 MySQL SQL
RDS MySQL 8.0 Statement queue
【7】Statement Queue 背景 MySQL 的 server 层和引擎层在 statement 并发执行过程中,有很多串行化的点,在 DML 语句中,事务锁冲突比较常见,InnoDB 中事务锁的最细粒度是行级锁,如果语句针对相同行进行并发操作,会导致冲突比较严重,系统吞吐量会随着并发的增加而递减。
1807 0
|
关系型数据库 PostgreSQL 数据库连接