资讯详情

【MySQL】访问 数据流动原理

📅 2026/11/2 6:34:48 | 华诺云谱 👁 阅读
【MySQL】访问  数据流动原理
欢迎来到MySQL专栏博客主页张小姐的猫~江湖背景所属专栏MySQL实战作者水平很有限如果发现错误可在评论区指正感谢MySQL欢迎来到MySQL专栏链接上数据库MySQL接口介绍C 查询处理细节连接池原理简易网站数据流动如何进行写在最后链接上数据库#includeiostream#includemysql/mysql.hintmain(){std::coutmysql client version: mysql_get_client_info()std::endl;return0;}gtest.cc-o test-L/lib64/mysql-lmysqlclient;其中include包含所有的方法声明lib包含所有的方法实现打包成库lmysqlclient告诉要链接哪个库-L/lib64/mysql告诉去哪里能找到这个库头文件在include中能搜索的到mysql/mysql.h如果不加就要-I去手动链接./test mysql client version:5.7.44MySQL接口介绍要使用库必须先进行初始化初始化mysql_init()最后不用记得关闭mysql_close()MYSQL*mymysql_init(nullptr);初始化完毕之后必须先链接数据库在进行后续操作。mysql网络部分是基于TCP/IP的MYSQL*mysql_real_connect(MYSQL*mysql,constchar*host,constchar*user,constchar*passwd,constchar*db,unsignedintport,constchar*unix_socket,unsignedlongclientflag);#includeiostream#includestring#includemysql/mysql.hconststd::string host127.0.0.1;conststd::string userconnector;conststd::string passwordLjj747501;conststd::string dbconn;constunsignedintport3306;intmain(){MYSQL*mymysql_init(nullptr);if(mynullptr){std::cerrinit MySQL errorstd::endl;return1;}if(mysql_real_connect(my,host.c_str(),user.c_str(),password.c_str(),db.c_str(),port,nullptr,0)nullptr){std::cerrConnect MySQL errorstd::endl;return2;}std::coutConnect MySQL successstd::endl;mysql_close(my);return0;}链接成功~在conn库中创建出一个表mysqlcreatetableuser(-idbigintprimarykeyauto_increment,-namevarchar(20)notnull,-ageintnotnull,-telphonevarchar(32)unique-);紧接着下发mysql命令mysql_queryintmysql_query(MYSQL*mysql,constchar*q);第一个参数是初始化后的数据库名第二个参数为要执行的sql语句std::string sqlupdate user set namesheriy where id 1;intnmysql_query(my,sql.c_str());if(n0)std::coutsqlsuccessnstd::endl;elsestd::coutsqlfailednstd::endl;mysqlselect*fromuser;-------------------------|id|name|age|telphone|-------------------------|1|tom|18|123456|-------------------------⬇️ mysqlselect*fromuser;---------------------------|id|name|age|telphone|---------------------------|1|sheriy|18|123456|---------------------------那么如果我们插入中文字段呢会出现乱码问题std::string sqlinsert intouser(name,age,telphone)values(张三,18,123456);mysqlselect*fromuser;----------------------------------|id|name|age|telphone|----------------------------------|1|sheriy|18|123456||2|å¼ ä¸‰|18|12342256|----------------------------------建立好链接之后获取英文没有问题如果获取中文是乱码设置链接的默认字符集是utf8原始默认是latin1mysql_set_character_set(myfd,utf8);设置完后就能正常显示了mysqlselect*fromuser;--------------------------------------|id|name|age|telphone|--------------------------------------|1|sheriy|18|123456||2|å¼ ä¸‰|18|12342256||4|张三|18|123427878256|--------------------------------------C 查询处理细节当我们进行查询后我们来看看如何获取查询结果实际上执行结果会保存在my这个句柄里的包括了保留数据的缓冲区如果mysql_query返回成功那么我们就通过mysql_store_result这个函数来读取结果原型如下MYSQL_RES*mysql_store_result(MYSQL*mysql);该函数会调用MYSQL变量中的st_mysql_methods中的 read_rows 函数指针来获取查询的结果。同时该函数会返回MYSQL_RES这样一个变量该变量主要用于保存查询的结果。同时该函数malloc了一片内存空间来存储查询过来的数据所以我们一定要记的 free(result)不然是肯定会造成内存泄漏的。 执行完mysql_store_result以后其实数据都已经在MYSQL_RES变量中了mysql_free_result(res);把结果转储到MYSQL_RES结构体中MYSQL_RES*resmysql_store_result(my);if(nullptrres){ std::coutsqlmysql_store_result failed!nstd::endl;return4;}首先理解一下表结构其中竖列是表表的属性其他就是表的内容我们的数据不已经放在了my结构体里了吗为什么还需要进行转储呢首先MySQL将所有的数据读取出来的时候全部都当作字符串看待下面的api基本就是读取MYSQL_RES中的数据获取结果行数my_ulonglongmysql_num_rows(MYSQL_RES*res);获取结果列数unsignedintmysql_num_fields(MYSQL_RES*res);select*fromusersuccess0 行2列4那如果想要获取结果内容呢mysql_fetch_row它会返回一个变量MYSQL_ROW其实就是char **通过确定访问哪一行再进而确定哪一列MYSQL_ROWmysql_fetch_row(MYSQL_RES*result);for(inti0;irows;i){//类似于迭代器 逐行取出MYSQL_ROW rowmysql_fetch_row(res);for(intj0;jfields;j){std::coutrow[j]\t;//遍历行的每一个}std::cout\n;}获取列名mysql_fetch_fieldsMYSQL_FIELD*mysql_fetch_fields(MYSQL_RES*res);MYSQL_FIELD*fields_arraymysql_fetch_fields(res);for(inti0;ifields;i){std::coutfields_array[i].name\t;}std::cout\n;//✅️id name age telphone1sheriy181234564张三18123427878256最终版代码#includeiostream#includestring#includemysql/mysql.hconststd::string host127.0.0.1;conststd::string userconnector;conststd::string passwordLjj747501;conststd::string dbconn;constunsignedintport3306;intmain(){MYSQL*mymysql_init(nullptr);if(mynullptr){std::cerrinit MySQL errorstd::endl;return1;}if(mysql_real_connect(my,host.c_str(),user.c_str(),password.c_str(),db.c_str(),port,nullptr,0)nullptr){std::cerrConnect MySQL errorstd::endl;return2;}//设置链接的默认字符集是utf8mysql_set_character_set(my,utf8);std::string sqlselect * from user;intnmysql_query(my,sql.c_str());if(n0)std::coutsqlsuccessnstd::endl;else{std::coutsqlfailednstd::endl;return3;}MYSQL_RES*resmysql_store_result(my);if(nullptrres){std::coutsqlmysql_store_result failed!nstd::endl;return4;}//全部都是和结果集res有关introwsmysql_num_rows(res);//获取行数intfieldsmysql_num_fields(res);//获取列数std::cout行rowsstd::endl;std::cout列fieldsstd::endl;//属性MYSQL_FIELD*fields_arraymysql_fetch_fields(res);for(inti0;ifields;i){std::coutfields_array[i].name\t;}std::cout\n;//内容for(inti0;irows;i){//类似于迭代器 逐行取出MYSQL_ROW rowmysql_fetch_row(res);for(intj0;jfields;j){std::coutrow[j]\t;//遍历行的每一个}std::cout\n;}mysql_free_result(res);mysql_close(my);return0;}连接池原理在创建一批线程的同时 创建出MySQL对象也就是每个线程分配一个MySQL对象让多个线程预先和MySQL先建立好链接后续有任务到来就push到连接池里在进入while死循环之前先让MySQL先链接上 —— 再进入到对应的事件循环中那么每个线程都有自己的MySQL的句柄并且是链接好的classtask{private:std::string sql;// 要执行的SQL语句std::functionvoid(Result)cb;// 回调函数};sql告诉线程池需要执行什么SQLcb告诉线程池SQL执行完毕后应该如何处理结果线程池创建工作线程时就为每个工作线程创建一个独立的 MySQL 对象并提前调用mysql_real_connect()建立数据库连接连接成功后再进入while(true)事件循环。此后工作线程不断从任务队列中取出任务使用自己持有的 MySQL 连接执行 SQL执行完成后通过任务中封装的回调函数cb(res)将结果返回给业务逻辑然后继续处理下一个任务。这样每个线程都能复用自己的数据库连接避免频繁创建和销毁连接提高数据库访问效率。简易网站数据流动如何进行比如说一个用户逻辑是怎么走的 注册or登录用户 —— 服务器网站 —— 中间件 —— 数据库Web业务处理 C数据库负载均衡 MySQL集群定时同步用户访问网站浏览器向服务器发送 HTTP GET 请求获取注册页面或登录页面。用户提交信息用户填写用户名、密码等信息通过 HTTP POST 请求将数据发送给服务器。Web应用层处理Nginx / Tomcat 接收请求由 PHP、Python 或 Java 等应用程序提取 GET / POST 参数完成业务逻辑处理并生成对应的SQL请求。C负载均衡应用层将数据库请求交给 C 模块由 C 根据负载均衡策略从三个 MySQL 节点中选择一个节点将 SQL 请求转发过去。MySQL执行操作被选中的 MySQL 节点执行 INSERT、SELECT、UPDATE 等操作并将执行结果返回给 C 模块。结果返回用户C 将数据库执行结果返回给 Web 应用层应用层进一步处理后通过 HTTP 响应返回浏览器。MySQL数据同步三个 MySQL 节点之间按照设定的周期进行数据同步使各节点的数据保持一致用户通过浏览器发起 HTTP 请求Web应用层负责接收请求和处理业务逻辑。对于数据库查询优先访问缓存命中则直接返回未命中则通过 C 负载均衡模块选择一个 MySQL 节点执行查询并将结果写入缓存。对于数据写入或修改则选择一个 MySQL 节点执行操作并处理相关缓存更新。三个 MySQL 节点之间通过定时同步机制共享数据写在最后接下来登场的是
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑