引言
在上一篇文章中,我们学习了 MySQL 的安装配置、基本 SQL 操作以及 C 语言连接数据库。本文将继续深入,讲解 MySQL 的核心高级特性:事务与隔离级别、视图、以及复杂查询的基础。这些是面试中的高频考点,也是实际项目开发中保证数据一致性的关键技术。
第一部分:MySQL 体系结构
一、整体架构
| 组件 | 功能 |
|---|---|
| 连接池 | 管理客户端连接,支持高并发 |
| SQL 解析器 | 词法分析、语法分析 |
| 优化器 | 选择最优执行计划(如索引选择) |
| 存储引擎 | 负责数据读写,可插拔(默认 InnoDB) |
| 文件系统 | 数据最终持久化到磁盘 |
第二部分:C 语言查询数据
一、完整查询流程
#include <stdio.h> #include <stdlib.h> #include <mysql/mysql.h> int main() { // 1. 初始化连接句柄 MYSQL *conn = mysql_init(NULL); if (conn == NULL) { fprintf(stderr, "mysql_init 失败\n"); return -1; } // 2. 连接数据库 if (mysql_real_connect(conn, "127.0.0.1", "root", "123456", "c1100db", 3306, NULL, 0) == NULL) { fprintf(stderr, "连接失败: %s\n", mysql_error(conn)); mysql_close(conn); return -1; } printf("数据库连接成功!\n"); // 3. 执行查询 const char *sql = "SELECT * FROM student"; if (mysql_query(conn, sql) != 0) { fprintf(stderr, "查询失败: %s\n", mysql_error(conn)); mysql_close(conn); return -1; } // 4. 获取结果集 MYSQL_RES *result = mysql_store_result(conn); if (result == NULL) { fprintf(stderr, "获取结果失败: %s\n", mysql_error(conn)); mysql_close(conn); return -1; } // 5. 获取行数和列数 int num_rows = mysql_num_rows(result); unsigned int num_fields = mysql_num_fields(result); printf("行数: %d, 列数: %d\n", num_rows, num_fields); // 6. 逐行逐列打印 MYSQL_ROW row; while ((row = mysql_fetch_row(result))) { for (unsigned int j = 0; j < num_fields; j++) { printf("%s\t", row[j] ? row[j] : "NULL"); } printf("\n"); } // 7. 释放结果集和连接 mysql_free_result(result); mysql_close(conn); return 0; }编译运行:
gcc query.c -o query -lmysqlclient
./query
二、结果集处理要点
| API | 作用 | 返回值 |
|---|---|---|
mysql_store_result() | 获取结果集 | MYSQL_RES*,失败返回 NULL |
mysql_num_rows() | 获取行数 | int |
mysql_num_fields() | 获取列数 | unsigned int |
mysql_fetch_row() | 逐行读取 | MYSQL_ROW,读完返回 NULL |
mysql_free_result() | 释放结果集 | 无 |
重要提示:
MYSQL_ROW本质是char**,所有值都是字符串形式数值型数据需要手动转换(如
atoi(row[0]))结果集用完后必须调用
mysql_free_result()释放
第三部分:事务
一、什么是事务
事务是一组 SQL 语句组成的原子操作单元,要么全部执行成功,要么全部回滚。
二、ACID 特性
| 特性 | 说明 | 举例 |
|---|---|---|
| 原子性 (Atomicity) | 事务是不可分割的最小单元 | 转账的两步要么都成,要么都不成 |
| 一致性 (Consistency) | 事务前后数据状态保持一致 | 转账前后总金额不变 |
| 隔离性 (Isolation) | 事务之间互不干扰 | A 转账时 B 看不到中间状态 |
| 持久性 (Durability) | 提交后数据永久保存 | 断电重启后数据不丢失 |
面试重点:能够解释 ACID 四个特性及其含义。
三、事务操作命令
-- 开启事务 BEGIN; -- 或 START TRANSACTION; -- 执行 SQL 操作... INSERT INTO student VALUES (1005, '小王', 22); UPDATE student SET age = 23 WHERE id = 1005; -- 提交事务(永久保存) COMMIT; -- 回滚事务(撤销所有操作) ROLLBACK;四、C 语言中控制事务
// 开启事务 mysql_query(conn, "BEGIN"); // 执行多条 SQL mysql_query(conn, "UPDATE account SET balance = balance - 1000 WHERE id = 1"); mysql_query(conn, "UPDATE account SET balance = balance + 1000 WHERE id = 2"); // 提交事务 mysql_query(conn, "COMMIT"); // 如果出错,回滚 // mysql_query(conn, "ROLLBACK");第四部分:隔离级别
一、四种隔离级别
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 隔离性 |
|---|---|---|---|---|
| READ UNCOMMITTED(未提交读) | ✅ | ✅ | ✅ | 最低 |
| READ COMMITTED(提交读) | ❌ | ✅ | ✅ | 中 |
| REPEATABLE READ(可重复读) | ❌ | ❌ | ✅ | 较高 |
| SERIALIZABLE(可串行化) | ❌ | ❌ | ❌ | 最高 |
三种并发问题:
二、查看和设置隔离级别
-- 查看当前会话隔离级别
SELECT @@transaction_isolation;-- 查看全局隔离级别
SELECT @@global.transaction_isolation;-- 设置会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;-- 设置全局隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
三、可重复读 (REPEATABLE READ) 演示
这是 MySQL 默认的隔离级别。
四、提交读 (READ COMMITTED) 演示
五、隔离级别选择建议
| 场景 | 推荐级别 | 原因 |
|---|---|---|
| 银行转账 | SERIALIZABLE | 数据一致性要求极高 |
| 订单系统 | REPEATABLE READ | 默认,平衡性能与一致性 |
| 报表查询 | READ COMMITTED | 需要看到最新已提交数据 |
| 日志记录 | READ UNCOMMITTED | 性能优先,允许少量不一致 |
第五部分:视图
一、什么是视图
视图是虚拟表,不存储实际数据,数据来源于基本表的查询结果。
二、视图操作
-- 1. 创建视图 CREATE VIEW stu_view AS SELECT id, name FROM student; -- 2. 查询视图(和查表完全一样) SELECT * FROM stu_view; SELECT * FROM stu_view WHERE id > 1001; -- 3. 查看所有表(含视图) SHOW FULL TABLES; -- Base Table → 基本表 -- View → 视图 -- 4. 删除视图(不影响基本表数据) DROP VIEW stu_view;三、视图的优缺点
| 优点 | 缺点 |
|---|---|
| 保护数据安全(隐藏敏感字段) | 不存储数据,每次查询需重新执行 |
| 简化复杂查询(封装多表联查) | 性能低于直接查询基本表 |
| 减少数据冗余 | 复杂视图可能降低查询效率 |
| 灵活调整展示格式 | 部分视图不可更新 |
第六部分:索引简介
索引是提升查询性能的核心手段,底层通常采用B+树数据结构。
-- 创建索引 CREATE INDEX idx_name ON student(name); -- 查看索引 SHOW INDEX FROM student; -- 删除索引 DROP INDEX idx_name ON student;总结
一、事务与隔离级别
| 要点 | 说明 |
|---|---|
| 事务操作 | BEGIN → 执行SQL → COMMIT/ROLLBACK |
| ACID | 原子性、一致性、隔离性、持久性 |
| 默认隔离级别 | REPEATABLE READ(可重复读) |
| 隔离级别排序 | UNCOMMITTED < COMMITTED < REPEATABLE < SERIALIZABLE |
二、视图
CREATE VIEW 视图名 AS SELECT ... DROP VIEW 视图名; -- 视图不存数据,本质是封装的 SELECT 语句三、C 语言查询数据
mysql_init → mysql_real_connect → mysql_query → mysql_store_result → mysql_fetch_row (循环) → mysql_free_result → mysql_close四、一句话记忆
事务保证一组 SQL 要么全做要么全不做(ACID),隔离级别控制事务之间的可见性(默认可重复读),视图是封装好的虚拟表用于保护数据和简化查询,索引通过 B+树加速查询但增删改时会付出维护代价。