很多零基础同学在Linux 环境学习 C语言操作MySQL时卡死率极高依赖库缺失、编译未定义引用、MySQL服务启停失败、权限报错、路径错误。网上大部分教程混杂 Windows 内容导致 Linux 用户跟着操作全程报错、跑不通程序。本文纯 Linux 环境适配采用倒叙学习法先跑通核心流程再补齐理论细节。优先让大家快速跑出第一个连接、第一条数据操作、第一个完整项目拿到正向反馈再循序渐进夯实内功。全程聚焦Linux 实操命令、报错解决、环境配置零基础也能一次跑通。第一阶段Linux环境准备与第一个连接专治各种卡壳阶段目标完成 Linux 下 MySQL 服务部署、开发依赖安装、编译环境配置成功用C语言连接数据库打通全部前置流程。1.1 Linux 下 MySQL 安装与服务控制Linux 下 90% 连接失败都是服务未启动、自启未开启、密码未设置、远程绑定未开启。概念解释MySQL服务LinuxLinux 中 MySQL 是系统常驻服务开机可自启。所有数据库读写、SQL解析、数据存储都由mysqld 服务进程负责。C程序属于客户端必须保证服务处于running 运行状态才能连接。【 配图1MySQL 服务正常运行状态截图】1. Linux 安装 MySQLUbuntu/Debiansudo apt update sudo apt install mysql-server -y2. 核心服务命令Linux 必记# 查看服务状态 sudo systemctl status mysql # 启动服务 sudo systemctl start mysql # 停止服务 sudo systemctl stop mysql # 设置开机自启推荐 sudo systemctl enable mysql3. Linux 本地登录 MySQL#进入mysql mysql -uroot -p密码 Linux 最大坑点认证插件不兼容99%新手连接失败的元凶问题本质MySQL8.0 新版本默认认证插件为caching_sha2_password而 Linux 下 C语言依赖库libmysqlclient只支持老式插件mysql_native_password。这会导致密码明明正确C程序死活连接失败不属于代码问题、不属于服务问题是插件协议不兼容。根治命令密码设置为1ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 1;原理说明强制将root认证方式改为C语言库兼容的老式密码认证插件彻底解决连接拒绝、认证协议不匹配报错。设置完成后可普通登录mysql -u root -pLinux避坑总结1. 连接失败优先排查MySQL服务是否启动查看服务器状态是否是running状态2. 密码正确仍连不上一定是认证插件不兼容caching_sha2_password 不支持C客户端3. 必须改成mysql_native_password才能适配 Linux C 语言开发1.2 Linux C语言开发环境搭建Linux 原生 GCC 不自带 MySQL 开发库不装依赖直接编译必报未定义引用。这是 Linux 学习 C-MySQL 的最大卡点。新概念解释链接库 编译链接Linuxmysql_init、mysql_real_connect等函数不属于C标准库属于 MySQL 客户端动态库。Linux 编译时必须手动通过-lmysqlclient告知 GCC 链接该动态库否则编译器找不到函数实现。1. 安装 Linux 专属开发依赖sudo apt install libmysqlclient-dev -y该包提供MySQL头文件、动态链接库、开发依赖是Linux C操作MySQL的必备依赖。2. Linux 固定编译命令gcc 文件名.c -o 可执行名 -lmysqlclient报错解析缺少-lmysqlclient 找不到MySQL函数实现 编译失败。【 配图2缺少 -lmysqlclient 参数导致的 GCC 编译报错截图】1.3 Linux 下第一个C语言数据库握手程序核心概念解释MYSQL连接句柄MYSQL结构体用于保存一次数据库连接的全部信息地址、账号、字符集、连接状态Linux 下所有数据库操作必须依赖该句柄。Linux可直接运行连接测试代码#include stdio.h #include mysql/mysql.h int main() { //初始化数据库操作句柄 MYSQL *conn mysql_init(NULL); //参数mysql对象地址主机名或者ip地址用户密码数据库名端口号3306 unix socket路径默认为NULL客户端标志位默认为0 conn mysql_real_connect(conn, localhost, root, 1, C2603, 3306, NULL, 0); //建立与 MySQL 数据库服务端的真实 TCP 连接 if(conn NULL) { printf(数据库连接失败\n); return -1; } printf(Linux 环境 MySQL 连接成功\n); mysql_close(conn); return 0; }Linux 编译运行指令gcc conn_test.c -o conn_test -lmysqlclient./conn_test成功输出提示代表你已打通 Linux 下 C 与 MySQL 的开发环境【 配图3C 语言数据库连接成功终端截图】第二阶段核心SQL极速极简入门Linux终端实操阶段目标在 Linux 终端 MySQL 中完成建库、建表、增删改查为代码操作铺垫基础。2.1 极简建库建表概念解释数据库 数据表数据库独立数据仓库分类存储业务数据数据表二维表格真正存储行、列数据。Linux 终端 MySQL 操作语句通用# 创建项目专属数据库后续C代码统一使用 create database 数据库名; eg: create database testdb; #删除数据库 drop database 数据库名; # 查看所有数据库 show databases; # 进入数据库 use 数据库名; eg: use testdb;三大核心数据类型Linux开发通用INT整型存储ID、年龄、分数可以配合unsigned使用egint unsignedVARCHAR(n)可变长字符串存储姓名、文本节省服务器空间DATE日期类型存储时间日期表 创建/删除 语句#建表 create table 表名( 列名1 数据类型 约束可选 列名2 数据类型 约束可选 ... ); create table student ( id int not null, name varchar(20), age int ); #删表 drop table 表名;修改表名 语句alter table 原表名 rename [to] 新表名; -- 其中to可以省2.2⭐核心CRUD四板斧Linux终端实操* 概念解释CRUD数据库四大核心操作C(增)、R(查)、U(改)、D(删)所有C语言项目均基于此实现。1. 增加INSERT作用标准单行数据插入语法。语法insert into 表名 values(字段1值,字段2值,字段3值);按照数据表字段定义的固定顺序依次填入对应类型的数据数值类型无需加引号字符串、文本类型必须用单引号包裹执行后直接向数据表中新增一条完整数据。示例insert into student values(1,张三,18);补充也可以不按照固定顺序进行插入语法insert into 表名字段2,字段3,字段1 values(字段2值,字段3值,字段1值)示例insert into student(id,name,age) values(1,张三,18);2.查询SELECT作用该语句会读取目标数据表的全部行、全部列数据。语法select * from student;*是通配符代表查询表中所有字段from 表名指定查询的数据来源表。适合快速查看整张表内容新手调试首选。示例select * from student [where 条件];示例select * from student where age 18 and age 24;-- 支持逻辑运算 and, or , not使用distinct可以用来消除重复行select distinct addr from student;3.修改UPDATE作用条件更新语法。语法update 表名set 字段新值where 条件将条件符合的那一行中set后面对应的字段设置为新值无 where 条件会修改全表数据示例update student set age19 where id1;4.删除DELETE作用条件删除语法。语法delete from 表名 where 条件精准匹配并删除符合条件的单行/多行数据无WHERE条件会清空全表。示例delete from student where id1; -- 删除一行示例delete from student; -- 逐行删除支持回滚Linux新手强制注意改、删必须加WHERE条件Linux服务器无撤回误操作直接丢失数据* 修改表字段信息修改表--添加字段alter table 表名 add 列名 类型; 示例 alter table students add birthday datetime;修改字段-- 重新命名alter table 表名 change 原字段名 新字段名 类型及约束; 示例alter table students change birthday birth datetime;修改字段-- 不改名字alter table 表名 modify 列名 类型及约束; 示例alter table students modify birth date not null;修改表--删除字段alter table 表名 drop 列名 示例alter table students drop birth;第三阶段C 语言操作 SQL 核心 API 详解3.1核心API详解mysql_query函数原型int mysql_query(MYSQL *mysql, const char *query);参数释义mysql数据库连接句柄由mysql_init()、mysql_real_connect()初始化并连接成功的 MYSQL 指针querySQL 语句字符串无需带分号结尾可传入增、删、改、查任意合法SQL。函数作用执行任意 SQL 语句字符串是C语言操作MySQL的核心入口函数。返回值0 执行成功非 0 执行失败。适用场景增、删、改、查全部语句。mysql_store_result()函数原型MYSQL_RES *mysql_store_result(MYSQL *mysql);MYSQL_RES 结果集Linux内存中虚拟数据表存放全部查询数据函数作用将mysql_query()执行成功后的所有查询数据从 MySQL 服务端一次性读取到本地客户端内存生成一张内存中的虚拟数据表也就是MYSQL_RES 结果集。返回值读取成功返回MYSQL_RES* 结果集指针读取失败或无数据返回NULL。核心特点与强制规范1.仅限查询语句只对SELECT等有返回数据的SQL有效增删改语句不需要、也不能调用该函数。2.承上启下必备函数必须先执行mysql_query()执行SQL再调用本函数载入结果集最后才能使用mysql_fetch_row()逐行遍历数据。3.占用客户端内存结果集数据全部存储在当前程序的堆内存中Linux 系统不会自动回收遍历完毕必须配合mysql_free_result()手动释放。4.一次性载入特性会把本次查询的所有数据一次性读完载入内存适合数据量不大的新手项目学生管理系统等。但是当数据库中数据量很大时会一次性撑爆客户端内存一般不建议在数据量大的数据库中使用。场景选型推荐学习实训、小数据量项目优先使用mysql_store_result()代码简单易用线上生产、大批量数据遍历场景推荐使用mysql_use_result()流式逐行读取全程不缓存全量数据杜绝内存溢出问题。mysql_fetch_row()函数原型MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);MYSQL_ROW 行对象单行数据字符串数组通过下标读取列值函数作用逐行读取结果集MYSQL_RES中的数据每次调用只会读取一行读取成功后内部指针自动下移为下次读取做准备。返回值返回MYSQL_ROW类型本质是字符串数组char**数组中每一个元素对应当前行的每一列数据读完所有数据返回 NULL可作为循环终止条件。核心特点1.所有读取出来的数据全部是字符串格式哪怕数据库中是数字、日期C语言拿到的也是字符串需要自行强转/转换类型2. 必须搭配mysql_store_result()使用先拿到结果集再逐行抓取3.不能随机读取某一行只能从上到下顺序遍历。mysql_free_result()函数原型void mysql_free_result(MYSQL_RES *result);函数作用释放MYSQL_RES结果集占用的内存资源。Linux 系统中查询产生的结果集是堆内存资源不会自动回收必须手动释放。核心强制规范只要调用了mysql_store_result()获取了结果集代码结束前必须执行 mysql_free_result()否则会造成严重的内存泄漏长期运行会导致程序占用内存越来越大、服务器卡顿。使用时机所有数据遍历读取完毕后、关闭数据库连接之前。【 配图5结果集 API 执行流程图】3.2 数据插入示例#include stdio.h #include mysql/mysql.h int main() { MYSQL *conn mysql_init(NULL); conn mysql_real_connect(conn, localhost, root, 123456, testdb, 3306, NULL, 0); if(conn NULL) { printf(连接失败\n); return -1; } mysql_query(conn, select * from student); MYSQL_RES *res mysql_store_result(conn); if(res NULL) { printf(获取结果集失败\n); mysql_close(conn); return -1; } MYSQL_ROW row; while( (row mysql_fetch_row(res)) ! NULL ) { printf(ID:%s 姓名:%s 年龄:%s\n, row[0], row[1], row[2]); } mysql_free_result(res); mysql_close(conn); return 0; }编译运行gcc insert.c -o insert -lmysqlclient./insert3.3 查询代码示例#include stdio.h #include mysql/mysql.h int main() { MYSQL *conn mysql_init(NULL); conn mysql_real_connect(conn, localhost, root, 123456, testdb, 3306, NULL, 0); if(conn NULL) { printf(连接失败\n); return -1; } mysql_query(conn, select * from student); MYSQL_RES *res mysql_store_result(conn); if(res NULL) { printf(获取结果集失败\n); mysql_close(conn); return -1; } MYSQL_ROW row; while( (row mysql_fetch_row(res)) ! NULL ) { printf(ID:%s 姓名:%s 年龄:%s\n, row[0], row[1], row[2]); } mysql_free_result(res); mysql_close(conn); return 0; }编译运行gcc insert.c -o insert -lmysqlclient./insertLinux开发硬性规范必须mysql_free_result()释放结果集服务器长期运行不释放会累积内存泄漏。第四阶段Linux 学生信息管理系统完整可运行项目阶段目标实现 Linux 终端交互式管理系统模块化代码、动态SQL拼接完整落地项目。1. 动态SQL拼接释义通过sprintf将用户终端输入的变量拼接为SQL语句实现动态数据操作是Linux交互式项目核心。2. Linux 完整项目源码#include stdio.h #include string.h #include mysql/mysql.h // 新增学生 void add_student(MYSQL *conn) { int id,age; char name[30]; char sql[128]; printf(请输入学生ID、姓名、年龄); scanf(%d%s%d,id,name,age); sprintf(sql,insert into student values(%d,%s,%d),id,name,age); if(mysql_query(conn,sql) 0) printf(✅ 添加成功\n); else printf(❌ 添加失败\n); } // 查询所有学生 void show_student(MYSQL *conn) { mysql_query(conn,select * from student); MYSQL_RES *res mysql_store_result(conn); MYSQL_ROW row; printf(\n 学生列表 \n); while( (row mysql_fetch_row(res)) ! NULL ) { printf(ID:%-4s 姓名:%-6s 年龄:%s\n,row[0],row[1],row[2]); } mysql_free_result(res); } // 修改学生信息根据ID修改年龄 void update_student(MYSQL *conn) { int id,new_age; char sql[128]; printf(请输入要修改的学生ID、新年龄); scanf(%d%d,id,new_age); sprintf(sql,update student set age%d where id%d,new_age,id); if(mysql_query(conn,sql) 0) printf(✅ 修改成功\n); else printf(❌ 修改失败\n); } // 删除学生信息根据ID删除 void del_student(MYSQL *conn) { int id; char sql[128]; printf(请输入要删除的学生ID); scanf(%d,id); sprintf(sql,delete from student where id%d,id); if(mysql_query(conn,sql) 0) printf(✅ 删除成功\n); else printf(❌ 删除失败\n); } int main() { MYSQL *conn mysql_init(NULL); conn mysql_real_connect(conn,localhost,root,123456,testdb,3306,NULL,0); if(conn NULL) { printf(数据库连接失败\n); return -1; } printf(数据库连接成功\n); int choice; while(1) { printf(\n 学生管理系统(Linux) \n); printf(1. 添加学生\n); printf(2. 查看学生\n); printf(3. 修改学生年龄\n); printf(4. 删除学生信息\n); printf(0. 退出系统\n); printf(请输入操作选项); scanf(%d,choice); if(choice 1) add_student(conn); else if(choice 2) show_student(conn); else if(choice 3) update_student(conn); else if(choice 4) del_student(conn); else if(choice 0) break; else printf(输入错误\n); } mysql_close(conn); return 0; }Linux 编译运行命令gcc student_sys.c -o student_sys -lmysqlclient./student_sys第五阶段Linux 生产级进阶知识阶段目标适配 Linux 服务器开发掌握数据约束、高级查询、事务、运维备份。5.1 表约束Linux服务端数据安全必备概念释义约束是数据库自动校验规则防止服务器存入脏数据。PRIMARY KEY主键唯一标识NOT NULL非空约束UNIQUE字段唯一DEFAULT默认值AUTO_INCREMENT自增主键create table student( id int primary key auto_increment, name varchar(20) not null, age int default 18, unique(name) );5.2 SQL高级查询与聚合函数1. 模糊查询select * from student where name like %张%;核心作用模糊匹配查询查询姓名中包含「张」字的所有学生数据。语法详解like模糊查询关键字替代精准相等匹配%通配符匹配任意字符、任意长度包含空字符%张%匹配规则前面不管是什么字、中间包含张、后面不管是什么字。拓展匹配规则张%以「张」开头张三、张伟%张以「张」结尾%张%包含「张」所有含张的名字。_ 替换一个-- 查询有两个字的名字 select name from student where name like __; -- 查询名字至少有2个字的名字 select name from student where name like __%;【 配图6模糊查询演示截图】2. 范围查询in, not int, 不连续范围between ... and ... not between ... and ... 连续范围空判断 is null判非空 is not null-- 查询年龄为18,20,24的学生信息 select name,age from student where age 18 or age20 or age 34 ; select name,age from student where age in (18,20,24); -- 查询年龄不是18,20,24的学生信息 select name ,age from student where age not in (18,20,24); -- 查询年龄在18到24岁之间的所有学生信息 select name, age from student where age between 18 and 24; -- 查询年龄不在18到24岁之间的 select * from student where age not between 18 and 24; -- 查询学生住址为空的学生 select * from student where addr is null;3. 排序order by字段 默认是升序 从小到大 asc, 需要降序从大到小 加上desc可以对多个字段进行判断-- 默认升序从小到大 ORDER BY 字段名; -- 等价于 ORDER BY 字段名 ASC; -- 降序从大到小 ORDER BY 字段名 DESC; -- 多个字段排序 ORDER BY 字段1, 字段2; -- 先按字段1升序再按字段2升序 ORDER BY 字段1 DESC, 字段2; -- 先按字段1降序再按字段2升序1️⃣ 单字段排序-- 查询年龄在18岁以上的学生年龄安从小到大 select * from student where age 18 order by age; -- 查询年龄在18岁以上的学生年龄安从大到小 select * from student where age 18 order by age desc;2️⃣ 多字段排序重要-- 先按年龄升序年龄相同的按身高降序 SELECT * FROM students ORDER BY age ASC, high DESC; -- 先按班级升序再按年龄降序 SELECT * FROM students ORDER BY cls_id ASC, age DESC; -- 先按性别男/女按字典序再按年龄降序 SELECT * FROM students ORDER BY gender, age DESC;4. 聚合函数count() 总数 max() 最大值 min() 最小值, sum()求和 avg() 平均值 round()四舍五入-- 查询男生有多少人 select count(*) from student where gender男; -- 查询最大年龄 select max(age) from student; -- 查询年龄最小值 select min(age) from student; -- 计算所有人的年龄总和 select sum(age) from student; -- 计算平均年龄 select avg(age) from student; select sum(age) / count(*) from student; -- 算平均年龄设置平均年龄的小数位数 select round(sum(age) / count(*),2) from student;5.分组查询group by 分组-- 按照性别分组 select * from student group by gender; -- 计算男生和女生的人数 select gender, count(*) from student group by gender; -- 计算每个性别中年龄最大的 select gender,max(age) from student group by gender; -- 查看性别分组中每个组的人名 select gender,group_concat(name) from student group by gender;6. 注意事项聚合函数count/avg/sum/max/min不需要遍历多行执行后直接返回单行统计结果C 语言读取时只需读取一行数据即可模糊查询like区分字符集Linux 环境 MySQL 建议统一 UTF-8避免中文匹配失效所有高级查询语句均可直接套入前文 C 语言mysql_query()中执行。5.3 Linux 下数据库事务保证多条 SQL要么全部成功、要么全部回滚保证数据一致性。1.什么是事务❓事务是一组不可分割的操作集合这些操作要么全部成功执行要么全部失败回滚保证数据的一致性和完整性2. 事务的四大特性ACIDAAtomic 原子性释义事务是一个不可分割的最小执行单元所有 SQL 要么全部执行成功要么全部失败回滚不存在部分执行、部分生效的中间状态。经典案例转账业务A扣款、B收款两条SQL必须同时成功任意一步失败全部撤销不能出现「A钱扣了、B没到账」的异常数据。CConsistency 一致性释义事务执行前后数据库的整体数据状态、数据约束始终保持合法一致不会出现逻辑错乱数据。经典案例两人转账无论转账成功或失败两人总金额始终保持不变不会凭空多钱、少钱保证数据逻辑合法。IIsolation 隔离性释义多个事务同时并发执行时各个事务之间相互隔离、互不干扰每个事务感知不到其他事务的存在不会出现数据覆盖、数据错乱问题。场景多人同时操作系统新增、修改数据各自事务独立运行不会互相影响执行结果。DDurability 持久性释义事务一旦执行COMMIT提交成功数据会永久写入数据库磁盘即使服务器宕机、程序崩溃、系统重启数据也不会丢失。3. 数据库的操作流程先开启事务明确事务的起点执行操作SQL语句的注入判断结果如果操作无误提交事务如果操作有误回滚事务撤销所有已执行的修改4. 事务的作用保证数据一致性避免部分操作成功部分数据失败导致混乱支持并发控制通过隔离性调节多个用户同时操作数据库时的冲突提供错误恢复机制操作失败可回滚减少数据损失风险5. 注意事项并非所有的数据库能支持事务MYSQL中的innoDB引擎支持但是MyISAM不支持事务开启之后需尽快提交或回滚避免长时间占用资源导致并发性能下降隔离性的权衡数据一致性越好并发效率越低需要根据实际情况调整隔离性6. 事务示例代码// C语言完整数据库事务 Demo可直接编译运行 #include stdio.h #include mysql/mysql.h int main() { // 1. 初始化并连接数据库 MYSQL *conn mysql_init(NULL); conn mysql_real_connect(conn, localhost, root, 123456, testdb, 3306, NULL, 0); if(conn NULL) { printf(数据库连接失败\n); return -1; } // 2. 关闭MySQL自动提交开启事务模式 mysql_query(conn, SET AUTOCOMMIT0); mysql_query(conn, BEGIN); // 3. 执行多条关联性SQL模拟转账/批量新增等关联业务 int ret1 mysql_query(conn, insert into student values(10,李四,20)); int ret2 mysql_query(conn, insert into student values(11,王五,21)); // 4. 事务判断全部执行成功则提交任意失败则回滚 if(ret1 0 ret2 0) { mysql_query(conn, COMMIT); printf(✅ 事务提交成功所有数据入库完成\n); } else { mysql_query(conn, ROLLBACK); printf(❌ 执行异常事务回滚无数据入库\n); } // 5. 恢复自动提交关闭连接 mysql_query(conn, SET AUTOCOMMIT1); mysql_close(conn); return 0; }事务核心原理详解1.默认机制MySQL 默认开启AUTOCOMMIT1每条SQL执行后立即自动提交无法回滚2.事务开启设置AUTOCOMMIT0BEGIN手动开启事务所有SQL操作会存入临时缓存不会直接写入数据库3.事务提交 COMMIT所有关联SQL执行无误手动提交数据永久落地数据库4.事务回滚 ROLLBACK任意一条SQL执行失败触发回滚撤销本次事务所有操作保证数据一致性5.适用场景批量新增、数据转账、关联修改等多条SQL必须同时成功/同时失败的业务场景。也可以直接在终端中进入mysql通过命令begin、commit、rollback来实现事务的开启、提交、回滚。rollback后事务会自动提交无需再commit来手动提交【 配图9事务三大操作命令行演示截图终端操作】全文总结本文为纯 Linux 环境专属教程从服务启停、依赖安装、编译指令、代码运行、项目实战全方位适配 Linux 系统规避所有 Windows 冗余内容解决新手环境报错、编译失败、连接失败等核心问题。全程遵循「先跑通、后理论」所有代码、命令均可在 Linux 一键复刻运行适合零基础入门、课程实训、小型服务器项目开发。