目录
- 开头
- [一.MySQL 用户管理](#一.MySQL 用户管理)
- [二.C 语言连接 MySQL:Connector/C](#二.C 语言连接 MySQL:Connector/C)
-
- 1.开发环境搭建
-
- [(1) Connector/C 库的目录结构](#(1) Connector/C 库的目录结构)
- (2)编译与运行
- 2.核心操作流程
-
-
- [a.第一步:初始化连接句柄 `mysql_init`](#a.第一步:初始化连接句柄
mysql_init) - [b.第二步:建立数据库连接 `mysql_real_connect`](#b.第二步:建立数据库连接
mysql_real_connect) - [c.第三步:执行 SQL 语句 `mysql_query`](#c.第三步:执行 SQL 语句
mysql_query) - [d.第四步:获取查询结果集 `mysql_store_result`](#d.第四步:获取查询结果集
mysql_store_result) - e.第五步:读取结果集数据
- f.第六步:释放资源与关闭连接
- [g.事务控制 API](#g.事务控制 API)
- [a.第一步:初始化连接句柄 `mysql_init`](#a.第一步:初始化连接句柄
-
- 结尾
- 往期回顾
开头
Ok了,今天这一期我们来一起学习MySQL的用户管理和如何用C语言对MySQL数据库的操作,废话不多说,我们直接开始
一.MySQL 用户管理
1.用户
MySQL 作为多用户数据库系统,默认的 root 账号拥有全局最高权限,若直接分配给所有使用者,会存在三大安全风险:
- 数据泄露风险:任意用户可访问所有数据库的全部数据
- 误操作风险:普通开发人员可删除库、修改系统配置
- 权限失控风险:无法按业务做数据隔离(如业务 A 的人员只能访问业务 A 的库)
用户管理的核心目标是最小权限原则:为不同角色创建独立账号,仅分配其工作必需的权限,实现数据与操作的隔离
(1)用户信息存储位置
MySQL 的所有用户信息、权限信息都存储在系统数据库 mysql 的 user 表中,这是权限体系的核心存储

如上图,MySQL中的用户信息都是存放在mysql 数据库中的 user 表中

三个核心字段含义:
user:用户名,仅用于身份标识host:允许该用户登录的主机地址,是安全控制的核心localhost:仅允许从数据库本机登录192.168.1.%:允许该网段的主机登录%:允许从任意主机登录(生产环境强烈不推荐)
authentication_string:经 MySQL 密码算法加密后的密码密文,5.7 版本后替代了旧版的password字段
(2)用户的唯一标识
MySQL 中用户不是仅由用户名唯一确定,而是由「用户名 + host 主机地址」共同唯一标识 。
例如:
'zhangsan'@'localhost'和'zhangsan'@'192.168.1.100'是两个完全独立的用户,密码、权限均可不同
(3)用户的基础操作
a.创建用户
语法格式:
create user '用户名'@'登陆主机/IP' identified by '密码';
示例 :创建一个只能本地登录的用户 yht,密码为 12345678
create user 'yht'@'localhost' identified by '12345678';
关键注意事项:
- 主机范围控制 :不要轻易创建
'user'@'%'这类允许任意地址登录的账号,会极大增加被暴力破解的风险。 - 密码策略限制 :MySQL 默认开启密码强度校验插件,简单密码会触发
ERROR 1819报错。- 查看密码策略:
SHOW VARIABLES LIKE 'validate_password%'; - 可根据场景调整策略等级、密码长度等参数,或使用符合复杂度要求的密码
- 查看密码策略:
b.删除用户
语法格式:
drop user '用户名'@'主机名';
c.修改用户密码
分为两种场景,对应不同语法:
-
普通用户修改自己的密码
set password = password('新密码');
-
root 用户修改指定用户的密码
set password for '用户名'@'主机名' = password('新密码');
其中 password() 是 MySQL 内置的密码哈希函数,会将明文密码加密为密文存储
2.权限管理机制
(1)权限体系概述
MySQL 权限按作用范围 从大到小可分为:全局层级 > 数据库层级 > 表层级 > 列层级 > 子程序层级。
按权限类型可分为数据操作、结构操作、管理操作三大类,核心权限如下:
表格
| 权限分类 | 具体权限 | 作用范围 |
|---|---|---|
| 数据操作 | SELECT、INSERT、UPDATE、DELETE | 表 / 列 |
| 结构操作 | CREATE、DROP、ALTER、INDEX | 库 / 表 |
| 视图 / 存储过程 | CREATE VIEW、EXECUTE、CREATE ROUTINE | 视图 / 子程序 |
| 系统管理 | CREATE USER、SUPER、SHOW DATABASES、FILE | 全局 |
(2)相关操作
a.赋权:grant
语法格式:
grant 权限列表 on 库.对象名 to '用户名'@'登陆位置' [identified by '密码'];
语法说明:
- 权限列表:多个权限用逗号分隔,
all [privileges]代表授予该范围下的所有权限 - 对象范围:
*.*:全局范围,所有数据库的所有对象库名.*:指定数据库下的所有表、视图等对象库名.表名:指定数据库下的某一张表
identified by:可选子句,用户已存在则同步修改密码,用户不存在则隐式创建用户(不推荐)
b.查看用户权限
show grants for 'whb'@'localhost';
c.权限回收:revoke
语法格式:
revoke 权限列表 on 库.对象名 from '用户名'@'登陆位置';
d.权限生效
-
通过
grant/revoke操作的权限,MySQL 会自动刷新权限缓存,立即生效。 -
若手动修改
mysql.user等系统表来变更权限,需要执行以下命令手动刷新才能生效:flush privileges;
二.C 语言连接 MySQL:Connector/C
Connector/C(也常称为 libmysqlclient)是 MySQL 官方提供的 C 语言编程接口,它封装了 MySQL 客户端 / 服务器的 TCP 通信协议与 SQL 交互逻辑,让 C/C++ 程序无需手动处理网络包、协议解析,只需通过函数调用即可完成数据库的全部操作。
核心交互模型
C 程序与 MySQL 的交互本质是「客户端 - 服务器」模型:
- C 程序作为客户端,通过 Connector/C 库向 MySQL 服务端发送 SQL 请求
- MySQL 服务端执行 SQL,将结果通过网络返回给客户端
- Connector/C 库解析返回的数据包,转换成 C 语言可读取的结构体与数据
1.开发环境搭建
(1) Connector/C 库的目录结构
下载后的开发包分为两大核心目录,分别对应编译期和运行期:
| 目录 | 作用 | 核心内容 |
|---|---|---|
include/ |
编译期:提供函数声明与结构体定义 | 核心头文件 mysql.h,以及辅助头文件:错误码定义、网络通信、内存管理、协议解析、字符集处理等 |
lib/ |
运行期:提供功能的二进制实现 | 静态库 libmysqlclient.a:编译时直接打包进可执行文件动态库 libmysqlclient.so(Linux):运行时动态加载,体积更小 |
(2)编译与运行
先写最简代码验证库是否能正常引入:


2.核心操作流程
C 语言操作 MySQL 遵循严格的线性流程:初始化句柄 → 建立连接 → 执行 SQL → 读取结果 → 释放资源 → 关闭连接
a.第一步:初始化连接句柄 mysql_init
函数原型
MYSQL *mysql_init(MYSQL *mysql);
作用
分配并初始化一个 MYSQL 结构体对象,它是所有数据库操作的核心上下文句柄,后续所有 API 都需要传入这个对象。
底层细节
MYSQL 结构体内部存储了:
- 连接基本信息:主机地址、端口、用户名、默认数据库、字符集
- 网络状态:套接字描述符、收发缓冲区
- 函数指针表
st_mysql_methods:封装了读行、写包、协议解析等底层操作,后续的查询、读结果都会调用这里的函数指针
参数与返回值
- 传
NULL:库内部自动申请内存,创建并返回新的MYSQL对象 - 传已有的
MYSQL地址:重新初始化该对象 - 返回值:成功返回有效指针,失败返回
NULL

b.第二步:建立数据库连接 mysql_real_connect
函数原型
MYSQL *mysql_real_connect(
MYSQL *mysql, // 初始化好的连接句柄
const char *host, // 数据库主机地址
const char *user, // 数据库用户名
const char *passwd, // 数据库密码
const char *db, // 默认连接的数据库,可传NULL
unsigned int port, // 数据库端口,默认3306
const char *unix_socket, // Unix套接字路径,一般传NULL
unsigned long clientflag // 客户端标志位,一般传0
);
底层执行流程
这个函数会完成完整的 MySQL 连接握手:
- 建立 TCP 网络连接(如果 host 是 IP)或 Unix 套接字连接(如果是 localhost)
- 与 MySQL 服务端协商协议版本、字符集
- 发送用户名、加密后的密码进行身份认证
- 建立会话,绑定默认数据库
参数说明
host:填localhost默认走 Unix 套接字(性能更高),填 IP 地址走 TCP 协议db:可以传NULL,连接后再通过 SQL 语句use 库名切换数据库clientflag:常用标志如CLIENT_MULTI_STATEMENTS支持一次执行多条 SQL,普通场景传 0 即可
中文乱码的解决方案
MySQL 连接默认字符集是 latin1,读取中文会出现乱码。连接成功后必须立即设置字符集:
mysql_set_character_set(conn, "utf8");
原理:保证「客户端连接字符集」和「数据库字符集」一致,避免字符转码错误。
返回值与错误处理
- 成功:返回传入的
MYSQL句柄 - 失败:返回
NULL,可通过mysql_error(conn)获取错误信息

c.第三步:执行 SQL 语句 mysql_query
函数原型
int mysql_query(MYSQL *mysql, const char *sql);
作用
将 SQL 语句发送给 MySQL 服务端执行,支持 SELECT、INSERT、UPDATE、DELETE 等所有类型的 SQL
参数与返回值
sql:要执行的 SQL 字符串,必须以\0结尾,末尾不需要加分号- 返回值:
0代表执行成功,非0代表执行失败
分类说明
- 非查询类 SQL(INSERT/UPDATE/DELETE) :执行成功后,可通过
mysql_affected_rows(conn)获取受影响的行数。 - 查询类 SQL(SELECT):执行成功只是代表服务端准备好结果了,数据还在服务端缓冲区,需要主动拉取到本地


d.第四步:获取查询结果集 mysql_store_result
函数原型
MYSQL_RES *mysql_store_result(MYSQL *mysql);
作用
一次性从服务端读取全部查询结果 ,缓存到本地内存中,返回一个 MYSQL_RES 结果集对象
内存泄漏风险 :该函数会自动 malloc 内存存储结果,使用完必须调用 mysql_free_result() 释放,否则会造成严重的内存泄漏。
返回值
成功返回 MYSQL_RES 结果集指针,失败返回 NULL
e.第五步:读取结果集数据
拿到结果集后,可以通过一组 API 获取元信息和逐行数据
- 获取结果集元信息
| 函数 | 作用 | 返回值 |
|---|---|---|
mysql_num_rows(res) |
获取结果的总行数 | my_ulonglong(无符号长整型) |
mysql_num_fields(res) |
获取结果的总列数 | unsigned int |
mysql_fetch_fields(res) |
获取所有列的字段信息 | MYSQL_FIELD* 数组,每个元素包含列名、字段类型、长度等 |
示例:获取并打印所有列名

- 逐行读取数据
mysql_fetch_row
函数原型
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
核心说明
MYSQL_ROW本质是char **类型,也就是字符串数组,每个元素对应一行中的一列数据。- 所有数据都以字符串形式返回,哪怕是数字类型,也会被转成字符串,需要自己做类型转换。
- 内部有行指针,每调用一次自动向后移动一行;读取完所有行后返回
NULL。 - 如果某字段值为
NULL,对应的数组元素是NULL,必须做空判断,否则会触发段错误

f.第六步:释放资源与关闭连接
-
释放结果集:查询操作结束后,必须释放结果集内存
mysql_free_result(res);
-
关闭数据库连接:程序退出前关闭连接,释放网络与句柄资源
mysql_close(conn);

g.事务控制 API
Connector/C 原生支持数据库事务控制,核心三个函数(仅 InnoDB 等支持事务的引擎有效):
| 函数 | 作用 | 参数说明 |
|---|---|---|
mysql_autocommit(my, mode) |
设置自动提交模式 | mode=1 开启自动提交(MySQL 默认);mode=0 关闭自动提交,开启手动事务 |
mysql_commit(my) |
提交事务 | 将当前事务的所有修改持久化到数据库 |
mysql_rollback(my) |
回滚事务 | 撤销当前事务所有未提交的修改 |
结尾
这一期对于MySQL的学习就到这里了,希望对你的学习有所帮助。感谢你的点赞、关注。我主页里有更好康的呦!