前面我们已经掌握了Linux网络编程的核心:TCP/UDP协议、Socket编程、线程池(半同步半异步模型),也实现了极简HTTP服务器。但实际的网络程序中,我们需要持久化存储数据——比如用户信息、接口请求记录、业务数据等,不能每次程序重启就丢失数据。

这时候就需要用到数据库,而MySQL是Linux环境下最常用、最主流的开源关系型数据库,也是网络编程中数据存储的首选。本节课,我们将从MySQL的安装配置入手,掌握基础SQL操作,重点学习Linux下C语言连接MySQL的方法,把数据库和之前的Socket编程结合起来,让我们的网络程序具备“数据持久化”能力。

核心重点:掌握Linux下MySQL的安装与基础配置、常用SQL语句(增删改查)、C语言连接MySQL的核心API与实操代码,理解数据库在网络编程中的应用场景,为后续开发完整的网络项目(如用户登录注册系统)打下基础。

一、MySQL基础认知

1. 什么是MySQL

MySQL是一款开源的关系型数据库管理系统(RDBMS),基于客户端-服务器(C/S)架构,底层通过TCP协议实现客户端与服务器的通信(默认端口3306),支持多用户、多线程并发访问,能高效存储和管理结构化数据。

在Linux网络编程中,MySQL的核心作用:作为网络程序的“数据仓库”,持久化存储业务数据(如TCP服务器的客户端信息、HTTP接口的请求日志、用户账号密码等),避免程序重启后数据丢失。

2. MySQL核心特点(贴合Linux网络编程)

开源免费:无需付费,可直接在Linux系统中安装部署,适配各类开源项目;

基于TCP通信:客户端与MySQL服务器通过TCP连接交互,和我们之前学的TCP Socket编程逻辑一致;

支持多并发:MySQL服务器支持多线程,可同时处理多个客户端(网络程序)的连接和数据操作;

结构化存储:以“数据库-表-字段”的层级存储数据,数据格式规范,便于查询和管理;

支持多种编程语言:提供C、C++、Python等多种语言的API,可轻松与Linux Socket程序结合。

3. 核心概念(必记)

数据库(Database):一个独立的数据存储容器,比如“linux_net”数据库,用于存储某个网络项目的所有数据;

表(Table):数据库中的最小数据存储单元,用于存储一类结构化数据(如“user”表存储用户信息);

字段(Field):表中的列,用于定义数据的类型(如id、name、age);

SQL语句:用于操作MySQL的指令,分为数据定义语言(DDL)、数据操作语言(DML)、数据查询语言(DQL)等;

MySQL客户端:用于连接MySQL服务器、执行SQL语句(如命令行客户端、C语言程序客户端);

MySQL服务器:运行在Linux系统中,负责接收客户端连接、执行SQL指令、管理数据存储。

二、Linux下MySQL安装与基础配置(实操重点)

Linux系统(Ubuntu/Debian、CentOS)安装MySQL的方式不同,我们分别讲解最常用的包管理器安装方法,步骤简洁,适合新手操作。

1. Ubuntu/Debian系统安装(推荐,贴合大多数学习环境)

步骤1:更新软件包索引

sudo apt update

步骤2:安装MySQL服务器

sudo apt install mysql-server -y

步骤3:启动MySQL服务并设置开机自启

# 启动服务
sudo systemctl start mysql
# 设置开机自启
sudo systemctl enable mysql
# 查看服务状态(确认启动成功)
sudo systemctl status mysql

启动成功提示:active (running)

步骤4:安全配置(关键,避免默认漏洞)

执行MySQL安全配置脚本,设置root密码、移除匿名用户、禁止远程root登录(初期学习推荐):

sudo mysql_secure_installation

按提示操作,重点步骤:

是否启用密码验证插件:输入 n(新手简化操作);

设置root用户密码:输入自定义密码(如123456,学习环境可简化,生产环境需复杂密码);

是否移除匿名用户:输入 y

是否禁止root远程登录:输入 y(后续需要远程连接再修改);

是否删除测试数据库:输入 y

是否刷新权限表:输入 y

步骤5:登录MySQL客户端

Ubuntu安装后,默认root用户通过auth_socket认证,需先切换到MySQL系统用户,再登录:

# 切换到mysql用户
sudo su - mysql
# 登录MySQL(无需输入密码,直接回车)
mysql -u root
# 退出登录
exit

若想通过密码登录,需修改root认证方式:

-- 登录后执行以下SQL
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';
-- 刷新权限
FLUSH PRIVILEGES;

修改后,可直接通过密码登录:mysql -u root -p,输入密码即可。

2. CentOS/RHEL系统安装

# 1. 添加MySQL官方YUM仓库
wget https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm
sudo rpm -ivh mysql80-community-release-el7-7.noarch.rpm

# 2. 安装MySQL服务器
sudo yum install mysql-server -y

# 3. 启动服务并设置开机自启
sudo systemctl start mysqld
sudo systemctl enable mysqld

# 4. 查看临时root密码(首次启动自动生成)
sudo grep 'temporary password' /var/log/mysqld.log

# 5. 安全配置(同Ubuntu,设置新密码、移除匿名用户等)
sudo mysql_secure_installation

# 6. 密码登录
mysql -u root -p

3. 基础配置(可选,适配网络编程)

若后续需要通过C语言程序(网络程序)远程连接MySQL,需修改配置文件,允许远程访问:

# 编辑MySQL配置文件(Ubuntu)
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
# 注释掉以下行(CentOS配置文件路径:/etc/my.cnf)
# bind-address = 127.0.0.1

# 重启MySQL服务,使配置生效
sudo systemctl restart mysql

同时,需给root用户授权远程访问权限(登录MySQL后执行):

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '你的密码' WITH GRANT OPTION;
FLUSH PRIVILEGES;

三、MySQL基础SQL操作(必掌握)

SQL(Structured Query Language,结构化查询语言)是操作MySQL的核心,我们重点掌握最常用的SQL语句,用于后续C语言程序操作数据库。所有操作均在MySQL客户端中执行。

1. 数据定义语言(DDL):创建/删除数据库、表

(1)数据库操作

-- 1. 创建数据库(用于存储网络程序数据,如linux_net)
CREATE DATABASE IF NOT EXISTS linux_net CHARACTER SET utf8;

-- 2. 查看所有数据库
SHOW DATABASES;

-- 3. 使用指定数据库(后续操作均基于该数据库)
USE linux_net;

-- 4. 删除数据库(谨慎操作,会删除所有数据)
DROP DATABASE IF EXISTS linux_net;

(2)表操作(以“user”表为例,存储客户端用户信息)

-- 1. 创建user表(id、用户名、密码、注册时间)
CREATE TABLE IF NOT EXISTS user (
    id INT AUTO_INCREMENT PRIMARY KEY,  -- 主键,自增(唯一标识每条数据)
    username VARCHAR(50) NOT NULL UNIQUE, -- 用户名,非空、唯一
    password VARCHAR(50) NOT NULL,      -- 密码,非空
    register_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 注册时间,默认当前时间
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- 2. 查看当前数据库的所有表
SHOW TABLES;

-- 3. 查看表结构(字段、类型、约束)
DESC user;

-- 4. 修改表结构(如添加age字段)
ALTER TABLE user ADD age INT;

-- 5. 删除表(谨慎操作)
DROP TABLE IF EXISTS user;

说明:ENGINE=InnoDB是MySQL默认的存储引擎,支持事务、主键约束等核心功能,适合网络编程中的数据存储需求。

2. 数据操作语言(DML):增删改数据

-- 1. 插入数据(新增用户,适配用户注册功能)
INSERT INTO user (username, password) VALUES ('zhangsan', '123456');
INSERT INTO user (username, password, age) VALUES ('lisi', '654321', 20);

-- 2. 修改数据(修改用户密码)
UPDATE user SET password = '111111' WHERE username = 'zhangsan';

-- 3. 删除数据(删除指定用户)
DELETE FROM user WHERE id = 1; -- 按主键删除,避免误删

3. 数据查询语言(DQL):查询数据

-- 1. 查询所有用户数据
SELECT * FROM user;

-- 2. 查询指定字段(用户名、密码)
SELECT username, password FROM user;

-- 3. 条件查询(查询用户名是lisi的用户,适配用户登录验证)
SELECT * FROM user WHERE username = 'lisi' AND password = '654321';

-- 4. 排序查询(按注册时间降序)
SELECT * FROM user ORDER BY register_time DESC;

-- 5. 统计查询(统计用户总数)
SELECT COUNT(*) FROM user;

4. 常用补充:权限管理(贴合网络编程)

网络程序中,建议创建专门的数据库用户,避免使用root用户(降低安全风险):

-- 创建用户(用于C语言网络程序连接)
CREATE USER 'net_user'@'localhost' IDENTIFIED BY 'net123456';

-- 授权:允许该用户操作linux_net数据库的所有表
GRANT ALL PRIVILEGES ON linux_net.* TO 'net_user'@'localhost';

-- 刷新权限
FLUSH PRIVILEGES;

四、Linux下C语言连接MySQL(核心,贴合网络编程)

我们之前写的TCP/UDP服务器、HTTP服务器,都是“内存级”的程序,数据存储在内存中,重启后丢失。现在通过C语言连接MySQL,将数据持久化到数据库中,实现“用户登录、注册”等具备数据存储能力的网络功能。

1. 准备工作:安装MySQL开发库

C语言连接MySQL需要依赖MySQL的开发库(头文件、链接库),执行以下命令安装:

# Ubuntu/Debian
sudo apt install libmysqlclient-dev -y

# CentOS/RHEL
sudo yum install mysql-devel -y

2. 核心API(必记,简化理解)

MySQL提供了专门的C语言API,核心函数如下(结合代码理解,无需死记硬背):

mysql_init():初始化MySQL连接句柄(类似创建Socket文件描述符);

mysql_real_connect():建立与MySQL服务器的连接(类似connect());

mysql_query():执行SQL语句(核心,如插入、查询数据);

mysql_store_result():获取查询结果(查询操作专用);

mysql_fetch_row():遍历查询结果集;

mysql_error():获取错误信息(调试必备);

mysql_close():关闭MySQL连接(类似close())。

3. 实操代码:C语言连接MySQL,实现用户注册与登录验证

结合之前的TCP Socket编程思路,编写一个简单的C语言程序,实现连接MySQL、用户注册(插入数据)、用户登录(查询数据)功能,代码有详细注释,可直接编译运行。

代码示例(mysql_demo.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql.h> // MySQL开发库头文件

// MySQL连接参数(根据自己的配置修改)
#define MYSQL_HOST "localhost"   // 服务器地址(本地为localhost)
#define MYSQL_USER "net_user"    // 数据库用户(之前创建的net_user)
#define MYSQL_PWD "net123456"    // 密码
#define MYSQL_DB "linux_net"     // 数据库名称
#define MYSQL_PORT 3306          // MySQL默认端口

// 错误处理宏
#define CHECK_ERROR(ret, msg) \
    if (ret) { \
        fprintf(stderr, "%s: %s\n", msg, mysql_error(&mysql)); \
        mysql_close(&mysql); \
        exit(1); \
    }

int main() {
    MYSQL mysql; // MySQL连接句柄(类似Socket的fd)
    int ret;

    // 1. 初始化MySQL连接句柄
    mysql_init(&mysql);

    // 2. 建立与MySQL服务器的连接
    if (!mysql_real_connect(&mysql, MYSQL_HOST, MYSQL_USER, MYSQL_PWD, 
                            MYSQL_DB, MYSQL_PORT, NULL, 0)) {
        fprintf(stderr, "连接MySQL失败: %s\n", mysql_error(&mysql));
        mysql_close(&mysql);
        exit(1);
    }
    printf("连接MySQL成功!\n");

    // 3. 设置字符集(避免中文乱码)
    ret = mysql_query(&mysql, "SET NAMES utf8");
    CHECK_ERROR(ret, "设置字符集失败");

    // --------------------------
    // 功能1:用户注册(插入数据)
    // --------------------------
    char username[50] = "wangwu";
    char password[50] = "wangwu123";
    char sql[200];
    // 拼接SQL语句(插入用户数据)
    sprintf(sql, "INSERT INTO user (username, password) VALUES ('%s', '%s')", 
            username, password);
    ret = mysql_query(&mysql, sql);
    CHECK_ERROR(ret, "用户注册失败");
    printf("用户注册成功!\n");

    // --------------------------
    // 功能2:用户登录(查询数据)
    // --------------------------
    char login_user[50] = "wangwu";
    char login_pwd[50] = "wangwu123";
    // 拼接SQL语句(条件查询)
    sprintf(sql, "SELECT * FROM user WHERE username='%s' AND password='%s'", 
            login_user, login_pwd);
    ret = mysql_query(&mysql, sql);
    CHECK_ERROR(ret, "登录查询失败");

    // 获取查询结果集
    MYSQL_RES *res = mysql_store_result(&mysql);
    if (res == NULL) {
        fprintf(stderr, "获取结果集失败: %s\n", mysql_error(&mysql));
        mysql_close(&mysql);
        exit(1);
    }

    // 遍历结果集(判断是否查询到用户)
    MYSQL_ROW row; // 一行数据
    if ((row = mysql_fetch_row(res)) != NULL) {
        printf("登录成功!用户信息:id=%s, username=%s\n", row[0], row[1]);
    } else {
        printf("登录失败!用户名或密码错误\n");
    }

    // 4. 释放资源、关闭连接
    mysql_free_result(res); // 释放结果集
    mysql_close(&mysql);    // 关闭MySQL连接
    printf("MySQL连接已关闭\n");

    return 0;
}
    

4. 编译与运行

编译时,需要链接MySQL的动态库(-lmysqlclient),执行以下命令:

# 编译代码(注意:-lmysqlclient 必须放在最后)
gcc mysql_demo.c -o mysql_demo -lmysqlclient

# 运行程序
./mysql_demo

5. 预期运行结果

连接MySQL成功!
用户注册成功!
登录成功!用户信息:id=3, username=wangwu
MySQL连接已关闭

运行后,可在MySQL客户端中执行 SELECT * FROM user;,查看新增的用户数据,验证程序是否生效。

6. 注意事项(避坑重点)

编译时必须添加 -lmysqlclient,否则会提示“未定义的引用”(链接失败);

确保MySQL服务已启动,连接参数(用户名、密码、数据库名)正确;

中文乱码问题:必须执行 SET NAMES utf8,且数据库、表的字符集均为utf8;

SQL语句拼接时,注意字符串格式(如用户名、密码需加单引号);

查询数据后,必须用 mysql_free_result() 释放结果集,避免内存泄漏。

五、MySQL与Linux网络编程的结合场景

学习MySQL的核心目的,是为了让我们的网络程序具备“数据持久化”能力,常见结合场景:

  1. TCP服务器:存储客户端连接信息、通信日志、用户账号密码(如聊天服务器的用户数据);

  2. HTTP服务器:存储接口请求记录、用户会话信息、网页数据(如简易网站的用户注册登录);

  3. 高并发场景:结合线程池(半同步半异步模型),让工作线程异步处理数据库操作,避免主线程阻塞。

例如:我们之前写的TCP多线程服务器,可修改为“主线程accept接收连接,工作线程处理用户登录/注册(操作MySQL)”,实现一个具备用户管理功能的完整TCP服务器。

六、常见问题与解决方案

1. 编译失败:未定义的引用(如mysql_init、mysql_real_connect)

解决方案:编译时添加 -lmysqlclient,确保MySQL开发库已安装。

2. 连接MySQL失败:Access denied for user 'xxx'@'localhost'

解决方案:检查用户名、密码是否正确;确认用户已授权(GRANT语句);重启MySQL服务。

3. 中文乱码

解决方案:1. 数据库、表的字符集设为utf8;2. C语言程序中执行mysql_query(&mysql, "SET NAMES utf8");3. 终端字符集设为utf8。

4. 程序运行时,MySQL服务突然断开

解决方案:检查MySQL服务状态(sudo systemctl status mysql),重启服务;检查网络连接,避免MySQL服务器端口被占用。

七、学习小结

1. MySQL是Linux网络编程中最常用的关系型数据库,基于TCP协议实现客户端-服务器通信,核心作用是持久化存储数据,避免程序重启后数据丢失。

2. 掌握Linux下MySQL的安装、安全配置、远程访问配置,能熟练使用常用SQL语句(增删改查),操作数据库和表。

3. 重点掌握C语言连接MySQL的核心API,能编写简单的数据库操作代码(注册、登录),实现网络程序的数据持久化。

4. MySQL与线程池、Socket编程结合,可实现高并发、具备数据存储能力的网络程序,这是后续开发完整项目的基础。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐