Linux下MySQL的简单使用
Linux下MySQL的简单使用
- 导语
- MySQL安装与配置
-
- MySQL安装
- 密码设置
- MySQL管理
-
- 命令
-
- myisamchk
- mysql
- 其他
- 常见操作
- C语言访问MYSQL
-
- 连接例程
- 错误处理
- 使用SQL
- 总结
- 参考文献
导语
这一章是MySQL的使用,一些常用的MySQL语句属于本科阶段内容,然后是C语言和MySQl之间的交互,可以看到C语言已经有成熟的和MySQL的接口
MySQL安装与配置
MySQL安装
MySQL的安装很简单,只需要执行几个shell命令就行,需要注意的是,对于Ubuntu新机器来说最好不要一开始就执行sudo apt update,因为很多包之间的依赖是复杂且未知的,如果直接全部更新可能会导致在跟书上同步实验时出问题(命令参考了ubuntu 23.10.1 mysql 安装)
sudo apt install mysql-server -y#这里就安装好了服务器
systemctl start mysql#开启mysql服务
systemctl status mysql#检查状态,如果出现mysql>就没问题sudo mysul -u root mysql#进入mysql
ps -el | grep mysqld#可以看mysql是否启动
下面这个是备选方案,是在新机器上装的
sudo apt-get update
sudo apt-get install libmysqlclient-dev
mysql_config --cflags
mysql_config --libs
后两条命令是检测MySQL Connector/C是否安装完成,由于新版本的MySQL已经不支持书上的写法,所以需要安装这个包,正常应该显示如下图

之后直接安装服务器即可
sudo apt-get update
sudo apt-get install mysql-server
通过下面的程序验证安装是否成功
#include <stdio.h>
#include <mysql/mysql.h>int main() {MYSQL *conn;conn = mysql_init(NULL);if (conn == NULL) {fprintf(stderr, "mysql_init() failed
");return EXIT_FAILURE;}if (mysql_real_connect(conn, "localhost", "user", "password", "database", 0, NULL, 0) == NULL) {fprintf(stderr, "mysql_real_connect() failed: %s
", mysql_error(conn));mysql_close(conn);return EXIT_FAILURE;}printf("Connected to the database successfully!
");mysql_close(conn);return EXIT_SUCCESS;
}
执行的命令和结果如下
gcc -o test_program test_program.c $(mysql_config --cflags) $(mysql_config --libs)

密码设置
一开始的root是没有密码的,可以通过命令查看各用户的密码如下,可以看到root密码为空

这里需要注意的是新版的MySQL和老版的不一样,新版本的password列改成了authentication_string
可以执行命令来设置密码,修改后查看,可以看到root有密码,但是被MySQL加密过了,再次登录时直接回车发现无法识别,只有输入密码才能识别用户

这里我们删除除去root之外的默认用户,并且删除从localhost以外任何主机的登录

到此为止,我们有了一个运行的MySQL,该MySQL只有设定密码的root通过本地才能连接,为了方便后续的操作,这里创建一个普通用户rick,它将能用三种方法来连接MySQL(本地连接,从IP连接,从wiley.com域中任何机器连接)
首先为rick创建一个本地登录,这里书上给的代码太老了,已经不适配现在的MySQL,更改成了现在版本的,最新的 MySQL 版本中,GRANT 语句不再用于设置用户密码。密码应该通过单独的 CREATE USER 或 SET PASSWORD 语句来设置。



通过三种不同的方式设置了三个用户,可以通过select命令展示,可以看到三种方式都成功了,并且rick的权利很大

MySQL管理
命令
所有命令都接受三个标准参数
-u 用于指定用户(用户名)
-p 用于提示密码(如果在命令行中未直接提供)
-h 用于指定主机(MySQL 服务器地址)
除了标准参数之外,每个命令还有自己的命令选项
myisamchk
通常情况下,myisamchk以创建的mysql用户运行并且工作目录为数据表在的目录中,常见的命令选项有
-c 检查表以发现错误
-e 执行扩展检查
-r 修复发现的错误
mysql
使用mysql可以不经过MySQL的控制台完成很多功能,通过在命令行最后添加数据库名称作为参数即可,可以通过 mysql --help | less来查看所有的命令行选项列表
其他
还有一些其他的命令,如mysqladmin、mysqlbug等,由于MySQL已经相对于书上更新很多了,所以很多命令已经过时,在此不多赘述
常见操作
书上提供的常见操作包括grant、revoke以及数据类型等,这些属于本科阶段SQL的基本内容,在此不再赘述,跳过
C语言访问MYSQL
连接例程
C语言连接MySQL需要先初始化一个连接句柄结构,然后再进行实际的连接,句柄通过mysql_init函数初始化,函数原型具体如下,mysql_init() 函数通常是在使用 MySQL 客户端 API 进行数据库编程时的第一个步骤。它为连接操作做了准备,确保在进行连接操作之前,连接对象处于一个已初始化的状态
MYSQL *mysql_init(MYSQL *);
//mysql:一个指向 MYSQL 结构体的指针。如果该指针为空,
//mysql_init() 将分配一个新的 MYSQL 结构体并返回它。如果提供了一个非空指针,它会用新的数据初始化该对象
真正与数据库进行连接的是mysql_real_connect函数,函数原型如下
MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *dbname, unsigned int port, const char *unix_socket, unsigned long client_flag);
//mysql是初始化之后的句柄
还有例程函数和关闭函数,在此不赘述
现在尝试创立一个数据库,向其中填入数据并通过C语言访问它

逐行输入对数据库的操作比较麻烦,并且容易出错,可以把要执行的命令单独做成文件,然后直接导入执行
-- Create the table childrenCREATE TABLE children (childno int(11) NOT NULL auto_increment,fname varchar(30),age int(11),PRIMARY KEY (childno)
);-- Populate the table 'children'INSERT INTO children (childno, fname, age) VALUES (1, 'Jenny', 21);
INSERT INTO children (childno, fname, age) VALUES (2, 'Andrew', 17);
INSERT INTO children (childno, fname, age) VALUES (3, 'Gavin', 8);
INSERT INTO children (childno, fname, age) VALUES (4, 'Duncan', 6);
INSERT INTO children (childno, fname, age) VALUES (5, 'Emma', 4);
INSERT INTO children (childno, fname, age) VALUES (6, 'Alex', 15);
INSERT INTO children (childno, fname, age) VALUES (7, 'Adrian', 9);


可以看到数据都被成功插入了
之后可以通过上述函数来连接数据库,由于系统和包之间的依赖问题以及mysql的版本问题,导致这个程序无法在旧机上运行,暂时没有找到解决方案,在新机上可以运行,运行结果和程序如下
#include <stdlib.h>
#include <stdio.h>
#include <mysql/mysql.h> // 包含新版 MySQL Connector/C 的头文件int main(int argc, char *argv[])
{MYSQL *con;// 初始化 MySQL 连接句柄con = mysql_init(NULL);if (con == NULL) {fprintf(stderr, "mysql_init() failed
");return EXIT_FAILURE;}// 连接数据库if (mysql_real_connect(con, "localhost", "rick", "111111", "foo", 0, NULL, 0) == NULL) {fprintf(stderr, "mysql_real_connect() failed
");fprintf(stderr, "Error: %s
", mysql_error(con));mysql_close(con);return EXIT_FAILURE;}// 输出连接成功状态printf("Connected successfully!
");// 关闭连接mysql_close(con);return EXIT_SUCCESS;
}

执行的时候需要添加对应的inlcude路径和库文件路径
错误处理
MySQL使用一系列由连接句柄结构报告的返回码来获取错误信息,具体的函数原型如下
unsigned int mysql_errno(MYSQL *connection);
//返回错误码
char *mysql_error(MYSQL *connection);
//返回有意义的文本信息
这里是书上给出的一个例子以及运行结果,可以看到屏幕上输出了错误信息
#include <stdio.h>
#include <stdlib.h>
#include <mysql.h>int main(int argc, char *argv[]) {MYSQL my_connection;mysql_init(&my_connection);if (mysql_real_connect(&my_connection, "localhost", "rick", "I do not know", "foo", 0, NULL, 0)) {printf("Connection success
");mysql_close(&my_connection);} else {fprintf(stderr, "Connection failed
");if (mysql_errno(&my_connection)) {fprintf(stderr, "Connection error %d: %s
",mysql_errno(&my_connection), mysql_error(&my_connection));}}return EXIT_SUCCESS;
}

使用SQL
这里直接给出一些C语言执行SQL语句的函数原型和简单解释
int mysql_query(MYSQL *connection, const char *query);
//第一个是初始化后的句柄,第二个是sql语句,返回错误码
my_ulonglong mysql_affected_rows(MYSQL *connection);
//查询上一条指令运行后影响了多少行
书上给出了一个使用AUTO_INCREMENT的代码实例,下面是修改后的程序和运行结果,AUTO_INCREMENT对每次插入的数据分配一个新的id值并进行追踪
#include <stdio.h>
#include <stdlib.h>
#include <mysql.h>#define DB_HOST "localhost"
#define DB_USER "rick" // 用户名 'rick'
#define DB_PASS "111111" // 数据库密码
#define DB_NAME "foo" // 数据库名称 'foo'// 错误处理函数,减少冗余代码
void handle_error(MYSQL *connection, const char *message) {fprintf(stderr, "%s
Error %d: %s
", message, mysql_errno(connection), mysql_error(connection));mysql_close(connection);exit(EXIT_FAILURE);
}int main(int argc, char *argv[]) {MYSQL my_connection;MYSQL_RES *res_ptr;MYSQL_ROW sqlrow;int res;// 初始化 MySQL 连接对象mysql_init(&my_connection);// 连接数据库if (!mysql_real_connect(&my_connection, DB_HOST, DB_USER, DB_PASS, DB_NAME, 0, NULL, 0)) {handle_error(&my_connection, "Connection failed");}printf("Connection success
");// 插入数据到表中res = mysql_query(&my_connection, "INSERT INTO children(fname, age) VALUES('Robert', 7)");if (res) {handle_error(&my_connection, "Insert error");} else {printf("Inserted %lu rows
", (unsigned long)mysql_affected_rows(&my_connection));}// 查询最后插入的数据res = mysql_query(&my_connection, "SELECT LAST_INSERT_ID()");if (res) {handle_error(&my_connection, "SELECT error");}// 获取查询结果res_ptr = mysql_use_result(&my_connection);if (res_ptr) {// 迭代结果集并输出while ((sqlrow = mysql_fetch_row(res_ptr))) {printf("We inserted childno %s
", sqlrow[0]);}// 释放结果集mysql_free_result(res_ptr);} else {fprintf(stderr, "Failed to retrieve result set.
");}// 关闭连接mysql_close(&my_connection);return EXIT_SUCCESS;
}
可以看到成功插入了一行,并且通过LAST_INSERT_ID拿到了ID

这里附上书上数据对应的插入代码
-- Create the table childrenCREATE TABLE children (childno INT(11) AUTO_INCREMENT NOT NULL PRIMARY KEY,fname VARCHAR(30),age INT
);-- Populate the table 'children'INSERT INTO children (fname, age) VALUES ('Jenny', 21);
INSERT INTO children (fname, age) VALUES ('Andrew', 17);
INSERT INTO children (fname, age) VALUES ('Gavin', 8);
INSERT INTO children (fname, age) VALUES ('Duncan', 6);
INSERT INTO children (fname, age) VALUES ('Emma', 4);
INSERT INTO children (fname, age) VALUES ('Alex', 15);
INSERT INTO children (fname, age) VALUES ('Adrian', 9);
INSERT INTO children (fname, age) VALUES ('Ann', 3);
INSERT INTO children (fname, age) VALUES ('Ann', 4);
INSERT INTO children (fname, age) VALUES ('Ann', 3);
INSERT INTO children (fname, age) VALUES ('Ann', 4);
除了上述两个基本的函数之外还有一些其他的函数,函数原型如下
MYSQL_RES *mysql_store_result(MYSQL *connection);
//从返回数据的语句中提取所有的数据,返回一个指向结果集的指针
my_ulonglong mysql_num_rows(MYSQL_RES *result);
//统计返回结果中的行数
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
//从结果集中提取一行,把这一行放在行机构里,每次使用一个
void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset);
//在结果集中跳转,第二个参数是行号,设置下一个被fetch操作返回的行
MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result);
//返回一个偏移值,表示结果集中的当前位置(不是行号)
void mysql_free_result(MYSQL_RES *result);
//对结果集的操作完成后,需要调用这个函数清理已经分配的对象
MYSQL_RES *mysql_use_result(MYSQL *connection);
//提取一行数据,返回指向对象的指针,不会缓存
//适合处理大数据量的查询结果,因为它允许逐行读取而不会将所有行一次性加载到内存中,这样可以有效减少内存的使用
unsigned int mysql_field_count(MYSQL *connection);
//获取最近一次查询的结果集中字段(列)的数量
MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result);
//用于从查询结果的字段列表中获取每个字段的描述信息,类似于字段的元数据。
//返回一个指向 MYSQL_FIELD 结构体的指针,这个结构体包含了字段的详细信息(例如字段名、类型等)。
下面是书上给出的一个综合程序(用chatgpt优化了),基本上用到了上面的所有函数,还有运行结果和具体的程序解释
#include <stdlib.h>
#include <stdio.h>
#include <mysql.h>// MySQL 连接对象和结果集
MYSQL my_connection;
MYSQL_RES *res_ptr;
MYSQL_ROW sqlrow;// 函数声明
void display_header();
void display_row();int main(int argc, char *argv[]) {int res;int first_row = 1; // 用于确保我们只显示一次表头// 初始化 MySQL 连接对象mysql_init(&my_connection);// 尝试连接到数据库if (mysql_real_connect(&my_connection, "localhost", "rick", "111111", "foo", 0, NULL, 0)) {printf("Connection success
");// 执行 SQL 查询,选择年龄大于 5 的记录res = mysql_query(&my_connection, "SELECT childno, fname, age FROM children WHERE age > 5");if (res) {// 查询执行失败,打印错误信息fprintf(stderr, "SELECT error: %s
", mysql_error(&my_connection));} else {// 使用 mysql_store_result() 获取结果集到内存res_ptr = mysql_store_result(&my_connection);if (res_ptr) {// 获取每行的数据并显示while ((sqlrow = mysql_fetch_row(res_ptr))) {if (first_row) {// 首次显示表头display_header();first_row = 0;}// 显示每行数据display_row();}// 释放结果集资源mysql_free_result(res_ptr);} else {// 获取结果集失败,打印错误信息fprintf(stderr, "Failed to retrieve result set: %s
", mysql_error(&my_connection));}}// 关闭数据库连接mysql_close(&my_connection);} else {// 连接失败,打印错误信息fprintf(stderr, "Connection failed
");if (mysql_errno(&my_connection)) {fprintf(stderr, "Connection error %d: %s
",mysql_errno(&my_connection), mysql_error(&my_connection));}}return EXIT_SUCCESS;
}// 显示表头,列出字段名称及其相关属性
void display_header() {MYSQL_FIELD *field_ptr;//获得列名printf("Column details:
");while ((field_ptr = mysql_fetch_field(res_ptr)) != NULL) {// 显示字段的名称printf(" Name: %s
", field_ptr->name);printf(" Type: ");// 判断字段类型并显示if (IS_NUM(field_ptr->type)) {//数字printf("Numeric field
");} else {switch (field_ptr->type) {//字符串case FIELD_TYPE_VAR_STRING:printf("VARCHAR
");break;case FIELD_TYPE_LONG:printf("LONG
");break;default:printf("Type is %d, check in mysql_com.h
", field_ptr->type);}}// 显示字段的最大长度printf(" Max width %ld
", field_ptr->length);// 检查字段是否具有 AUTO_INCREMENT 属性if (field_ptr->flags & AUTO_INCREMENT_FLAG) {printf(" Auto increments
");}printf("
");}
}// 显示查询结果的每一行
void display_row() {unsigned int field_count;// 遍历每一列,打印其值field_count = 0;while (field_count < mysql_num_fields(res_ptr)) {//如果域名数量比当前索引大if (sqlrow[field_count]) {//sqlrow存了这一行的数据printf("%s ", sqlrow[field_count]);} else {printf("NULL ");}field_count++;}printf("
");
}

还有更多的函数,在此不再赘述,可以查看MYSQL手册相关
总结
可以看到C语言已经有了很成熟的与MySQL交互的接口,并且大部分函数的使用是和MySQL版本不相关的,但实际在Ubuntu运行的时候还是需要注意MySQL的版本和包的问题,因为新版本的MySQL库修改了一些配置文件的位置和相关的依赖包
参考文献
- ubuntu 23.10.1 mysql 安装
- ChatGPT
相关文章:
Linux下MySQL的简单使用
Linux下MySQL的简单使用 导语MySQL安装与配置 MySQL安装密码设置 MySQL管理 命令 myisamchkmysql其他 常见操作 C语言访问MYSQL 连接例程错误处理使用SQL 总结参考文献 导语 这一章是MySQL的使用,一些常用的MySQL语句属于本科阶段内容,然后是C语言和M…...
.net core使用AutoMapper
AutoMapper 是一个用于 .NET 平台的对象映射工具,它简化了不同对象类型之间的转换过程。在软件开发中,尤其是在分层架构的应用程序里,常常需要在不同的对象模型之间进行数据传递,例如从数据库实体到视图模型、DTO(数据…...
nmap详解
Nmap(Network Mapper)是一个开放源代码的网络探测和安全审核的工具。由于它的功能强大,被广泛应用于网络安全领域。以下是Nmap的一些主要功能及其在实战中的应用举例。 Nmap的主要功能: 端口扫描:检测目标主机上开放…...
CentOS7环境安装php
直接安装 yum -y install php CentOS7默认安装是php5,现在php已有8.3版本 先查看php -v 版本 如果是低版本,可以删除 yum remove php yum remove php-fpm yum remove php-common 一、添加REMI存储库 yum install epel-release yum install -y …...
基于深度学习的猫狗识别系统【深度学习课设】
🏆 作者简介:席万里 ⚡ 个人网站:https://dahua.bloggo.chat/ ✍️ 一名后端开发小趴菜,同时略懂Vue与React前端技术,也了解一点微信小程序开发。 🍻 对计算机充满兴趣,愿意并且希望学习更多的技…...
字体子集化实践探索
最近项目rust生成PDF组件printpdf需要内嵌完整字体导致生成的PDF很大,需要做压缩,但是rust的类库allsorts::subset::subset不支持windows,所以做了一些windows下字体子集化的尝试 方案一:node.js做子集化 fontmin 缺点是也需要集…...
A1017 基于Java+JSP+SQL Server+servlet的二手购物平台的设计与实现
二手购物平台 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 摘 要 计算机以及网络技术的飞速发展,网络的应用在全国乃至全球日益普及,随着人们的思想水平和生活水平的提高,网络已经是人们必不可少的一部分。人们的…...
Simdroid-EC:液冷仿真新星,助力新能源汽车电机控制器高效散热
近年来,新能源电动车的销量呈现出快速增长的态势。据统计,2024 年1-10月中国新能源汽车销量达728万辆,同比增长37.8%。 电机控制器在新能源汽车中对于保障动力和安全性能扮演着至关重要的角色,其核心部件IGBT(绝缘栅双…...
C语言——实现并求出两个数的最大公约数
问题描述:求出两个数的最大公约数 //求两个数的最大公约数 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<time.h>int main() {int a,b;printf("请您输入两个数 a 和 b\n");scanf…...
今天你学C++了吗?——C++中的类与对象(日期类的实现)——实践与知识的碰撞❤
♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…...
享元模式的理解和实践
在软件开发中,性能优化是一个永恒的话题。在追求高性能的过程中,减少内存的使用是一项重要的任务。享元模式(Flyweight Pattern)就是一种用于减少内存使用量的设计模式,它特别适用于存在大量重复对象的场景。本文将详细…...
Unreal Engine 中的UI界面开发
推荐的使用方式 轻量级 HUD:使用 Canvas 绘制简单的文本、调试信息或基础 UI(如准星、血量条等)。 复杂 UI:使用 UMG(Unreal Motion Graphics)和 Slate 进行布局和交互,避免手动管理 Canvas 绘制。 避免遮挡场景:仅绘制必要的内容,并利用透明度(如 FLinearColor(1, 1…...
Docker在Ubuntu和CentOS系统下的安装
目录 1. 各版本平台支持情况2. 在Ubuntu系统下安装docker3. 常见报错4. Docker的镜像源修改5. Docker目录修改6. 在CentOS系统下安装docker 1. 各版本平台支持情况 (1)平台支持情况如下: Server 版本 桌面版本 2. 在Ubuntu系统下安装docker…...
EXCEL 关于plot 折线图--频度折线图的一些细节
目录 0 折线图有很多 1 频度折线图 1.1 直接用原始数据做的频度折线图 2 将原始数据生成数据透视表 3 这样可以做出了,频度plot 4 做按某字段汇总,成为累计plot分布 5 修改上面显示效果,做成百分比累计plot频度分布 0 折线图有很多 这…...
Hive操作案例
目录 idea/dg远程连接导入数据建表数据导入 idea/dg远程连接 hive的详细安装不多展示,自行搜索即可。 依次启动zookeeper,hadoop 在zookeeper的节点上启动如下指令(我的是1个主节点和2个备用节点) 启动Hive的metastore࿰…...
C++ 内存管理和模板与STL
此篇目是之后各种C库的基础 目录 内存管理 内存分布 内存管理方式 new和delete operator new 与 operator delete函数 实现原理 定位new表达式(placement-new) 模板基础 泛型编程 模板 函数模板 类模板 STL 组成部分 内存管理 内存分布 int globalVar 1; //全局变量 静…...
JDK8新特性:Stream
JDK8最大的改变: 1. lambda表达式 2. Stream 1. Steam流的入门 什么是Stream? 也叫Stream流,是jdk8开始的一套API,用于操作集合或者数组中的数据 优点: Stream流大量结合了Lambda的语法风格来创建,提…...
前端传入Grule,后端保存到 .grl 文件中
前端传入Grule,后端保存到 .grl 文件中 通过简单的输入框,将Grule的部分拆解成 规则名称 规则描述 规则优先级 规则条件 规则逻辑Grule关键字 when Then 模拟了 if 判断的条件和逻辑部分 类似于 shell 和 ruby 之类的脚本语言,有 then 关键字…...
探索《Crypto Rumble》 游戏:经济模型篇
《Crypto Rumble》是一款基于 Zypher Network 游戏引擎打造的卡牌 RPG三消品类的 Web3 游戏,通过引人入胜的游戏设计以及轻量化的游戏玩法,《Crypto Rumble》不仅能够为玩家带来引人入胜的沉浸式游戏体验,同时基于 AI Bot 的游戏编辑器&#…...
【CSS in Depth 2 精译_072】第 12 章 CSS 排版与间距概述 + 12.1 间距设置(上):究竟该用 em 还是 px
当前内容所在位置(可进入专栏查看其他译好的章节内容) 第四部分 视觉增强技术 ✔️【第 12 章 CSS 排版与间距】 ✔️ 12.1 间距设置 ✔️ 12.1.1 使用 em 还是 px ✔️12.1.2 对行高的深入思考12.1.3 行内元素的间距设置 文章目录 第 12 章 排版与间距…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
