C/C++ 连接访问 MySQL数据库

news2025/5/22 13:18:25

 

  前面我们已经讲述了MySQL的基础使用,现在我们来看一下如何使用语言来操作数据库。在实际开发中,语言连接MySQL是为了能够在编程语言中与MySQL数据库进行交互和操作。大部分情况我们都是通过语言连接MySQL,建立与MySQL数据库的连接,可以向MySQL数据库发送更新请求,如插入、更新或删除数据。本篇文章主要讲解使用C语言连接MySQL数据库,当然在C++中也能够使用,因为C++兼容C语言的

文章目录

一、连接MySQL

1、1 MySQL官网下载库

1、2 安装对应开发库

二、MySQL接口介绍

2、1 创建和释放 MYSQL 对象

2、2 连接mysql

2、3 发送sql语句


🙋‍♂️ 作者:@Ggggggtm 🙋‍♂️

👀 专栏:MySQL  👀

💥 标题:C/C++ 连接访问 MySQL💥

 ❣️ 寄语:与其忙着诉苦,不如低头赶路,奋路前行,终将遇到一番好风景 ❣️ 

一、连接MySQL

1、1 MySQL官网下载库

  要使用C语言连接mysql,需要使用mysql官网提供的库。MySQL官网:MySQL。如下图:

  然后点击DOWNLOADS,如下图:

  往下寻找MySQL Community Downloads,如下图:

  因为我们使用C语言连接MySQL,所以查找C API,如下图:

  然后点击如下图:

  我个人所用的是Linux,所以选择Linux的安装包。可根据自己的环境进行选择,如下图:

  再次选择OS合适的版本,如下图:

  当我们下载后,采用rz -E的方法可将压缩包传输到我们的Linux上。然后再使用 tar -xzf进行解压即可。解压后我们再看其中的文件,如下图:

  其中对我们有用的就是头文件和库函数了。具体怎么进行使用该头文件和库函数,可以参照文章:动静态库的原理与制作详解。这里就不再过多解释。

  但是我们也不建议使用以上方法,因为其中可能会产生兼容性等问题。我们接着往下看。

1、2 安装对应开发库

  当我们再Linux安装了mysql的开发环境时,就会自动给我们安装对应的语言连接mysql 的头文件与库函数。我们可以进行查看。具体查看方法如下:

  1. 查看头文件:
  2. 查看对应的库:

  如果上述都能够查看到,证明就已经安装了对应的开发库。一般情况下都是有的,如果没有的话,可以进行自己安装,如下图:

  我这里已经安装过了,所以最后显示的是Nothing to do。下面我们来验证一下看是否安装成功。代码如下:

#include <iostream>
#include <mysql/mysql.h>

int main()
{
    printf("mysql client Version: %s\n", mysql_get_client_info());
    return 0;
}

  运行结果如下图:

  到这里就证明已经安装成功对应的开发库了,且可以正常使用了。这里再说明一下:

  • 我们再包含头文件时,只需要包含mysql.h即可。但是需要添加上对应的mysql/mysql.h。因为g++编译器只会去include路径下寻找,而我们的头文件在include路径下的mysql文件夹中。
  • mysql_get_client_info()函数就是过去自身版本信息的一个函数。
  • 我们在使用g++进行编译时,还需要指明对应的库文件的搜索路径和所使用的库名称。g++编译器在编译时,只会寻找C++相关的库和系统自带的库。而我们自己安装的需要指明库的搜索路径和所用到的库名称。简单理解,就是告诉g++,我们所用到的库的路径。代码如下:
    g++ -o mytest mytest.cc -std=c++11 -L /lib64/mysql -lmysqlclient

二、MySQL接口介绍

2、1 创建和释放 MYSQL 对象

  函数原型:

MYSQL *mysql_init(MYSQL *mysql)

  该函数接受一个MYSQL类型的指针作为参数,一般我们都设置为NULL并返回一个MYSQL类型的指针,这个指针指向初始化后的MySQL连接句柄

  具体来说,mysql_init()函数完成以下几个任务:

  1. 分配内存空间:它会为MYSQL结构体类型的变量分配足够的内存空间。MYSQL结构体包含了与MySQL服务器通信所需的各种信息和状态。

  2. 初始化结构体成员:它会将MYSQL结构体中的各个成员初始化为默认值。这些成员包括连接属性、错误信息等。

  3. 返回连接句柄:它会返回指向初始化后的MYSQL结构体的指针,我们可以将这个指针保存下来,在后续的MySQL操作中使用。

  MYSQL结构体中包含了众多属性信息,具体如下:

typedef struct st_mysql {
	NET net;			/* Communication parameters */
    unsigned char	*connector_fd;		/* ConnectorFd for SSL */
    char *host,*user,*passwd,*unix_socket,*server_version,*host_info;
    char *info, *db;
    struct charset_info_st *charset;
    MYSQL_FIELD	*fields;
    MEM_ROOT field_alloc;
    my_ulonglong affected_rows;
    my_ulonglong insert_id;		/* id if insert on table with NEXTNR */
    my_ulonglong extra_info;		/* Not used */
    unsigned long thread_id;		/* Id for connection in server */
    unsigned long packet_length;
    unsigned int port;
    unsigned long client_flag,server_capabilities;
    unsigned int protocol_version;
    unsigned int field_count;
    unsigned int server_status;
    unsigned int server_language;
    unsigned int warning_count;
    struct st_mysql_options options;
    enum mysql_status status;
    my_bool	free_me;		/* If free in mysql_close */
    my_bool	reconnect;		/* set to 1 if automatic reconnect */

    /* session-wide random string */
    char scramble[SCRAMBLE_LENGTH+1];
    my_bool unused1;
    void *unused2, *unused3, *unused4, *unused5;

    LIST *stmts;                     /* list of all statements */
    const struct st_mysql_methods *methods;
    void *thd;
    /*
      Points to boolean flag in MYSQL_RES  or MYSQL_STMT. We set this flag
      from mysql_stmt_close if close had to cancel result set of this object.
    */
    my_bool *unbuffered_fetch_owner;
    /* needed for embedded server - no net buffer to store the 'info' */
    char *info_buffer;
    void *extension;
} MYSQL;

  需要注意的是,mysql_init()函数不会创建实际的连接;只是初始化了一个连接句柄,我们还需要通过其他函数(如mysql_real_connect())来建立与MySQL服务器的实际连接。后续会详细解释。

  在连接使用完成后,我们还需要通过mysql_close()函数关闭连接并释放内存。函数原型如下:

void mysql_close(MYSQL *connection);

参数:

  • connection:指向一个已经打开的MYSQL对象的指针。该对象代表与MySQL服务器的连接。

  该函数没有返回值。注意事项:

  1. 在调用mysql_close之前,确保已经完成了与数据库的所有操作,包括查询和事务等。
  2. 关闭连接后,将无法再使用该连接对象执行任何操作,除非重新使用mysql_real_connect建立新的连接。
  3. 对于多个线程同时共享一个连接对象的情况,应该确保在多个线程之间正确地协调和同步连接的打开和关闭操作,以避免出现竞态条件和意外错误。

2、2 连接mysql

  初始化完毕之后,必须先链接数据库,在进行后续操作。(mysql网络部分是基于TCP/IP的) 

  函数原型:

MYSQL *mysql_real_connect(MYSQL *mysql, const char *host,
    const char *user,
    const char *passwd,
    const char *db,
    unsigned int port,
    const char *unix_socket,
    unsigned long clientflag);

  参数说明:

  • mysql:一个预先分配和初始化的MYSQL对象指针。该指针用于保存与MySQL服务器的连接相关信息。
  • host:MySQL服务器的主机名或IP地址。
  • user:连接MySQL服务器所使用的用户名。
  • passwd:连接MySQL服务器所使用的密码。
  • db:连接成功后要使用的默认数据库名。
  • port:MySQL服务器的端口号。
  • unix_socket:Unix域套接字路径,用于本地连接Unix系统上的MySQL服务器,一般情况都属设置为nullptr。
  • client_flag:客户端标志位,用于指定连接选项。

  返回值:

  • 连接成功时,返回一个新的MYSQL对象指针,该对象与第一个参数的值相同,用于后续的MySQL操作。
  • 连接失败时,返回NULL,并通过调用mysql_errno()和mysql_error()函数获取错误代码和错误信息。

  使用mysql_real_connect函数,可以实现以下功能:

  1. 与MySQL服务器建立起连接。
  2. 指定要连接的数据库。

  接下来我们就来看一个实际的连接mysql的例子,代码如下: 

#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <mysql/mysql.h>

using namespace std;

const string Host = "127.0.0.1";
const string User = "gtm";
const string Passwd = "123654";
const string Db = "test";
unsigned int Port = 3306;

int main()
{
    MYSQL* my = mysql_init(NULL);
    if(my == nullptr)
    {
        cerr << "mysql init error!" << endl;
        exit(1);
    }
    cout << "mysql init success!" << endl;

    if(mysql_real_connect(my, Host.c_str(), User.c_str(), Passwd.c_str(), Db.c_str(), Port, nullptr, 0) ==nullptr)
    {
        cerr << "mysql connect error!" << endl;
        exit(2);
    }
    cout << "mysql connect success!" << endl;

    mysql_close(my);
    cout << "mysql close success!" << endl;    
    return 0;
}

  我们来看一下运行结果,如下图:

2、3 发送sql语句

  前面都是准备工作,现在我们可以向mysql发送sql指令了。函数原型:

int mysql_query(MYSQL *mysql, const char *query)

  该函数接受两个参数:一个是MYSQL结构体指针,代表与MySQL服务器的连接;另一个是一个字符串指针,代表要执行的SQL查询语句。

  函数返回一个整数值,用于表示查询执行的结果。如果执行成功,返回0;如果执行失败,返回非零值,表示出错的类型。在执行过程中,可以通过调用mysql_error()函数获取错误信息。

  稍微总结一下,使用mysql_query()函数执行SQL查询的一般步骤如下:

  1. 建立与MySQL服务器的连接,可以使用mysql_init()函数初始化一个MYSQL结构体,并通过mysql_real_connect()函数建立连接。

  2. 构造要执行的SQL语句,以字符串形式传递给mysql_query()函数。

  3. 调用mysql_query()函数执行SQL语句。

  4. 根据返回值判断查询执行结果,如果返回0,则表示执行成功;如果返回非零值,则表示执行失败。

  我们现在查看一下gtm用户下test数据库中都有哪些表,如下图:

  test库正式我们所连接的库。我们现在通过mysql_query函数向t1表中插入数据,我们先来看一下t1表中现有的数据,如下图:

  我们再来插入数据,代码如下:

#include <iostream>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <cstring>
#include <mysql/mysql.h>

using namespace std;

const string Host = "127.0.0.1";
const string User = "gtm";
const string Passwd = "gao520918";
const string Db = "test";
unsigned int Port = 3306;

int main()
{
    MYSQL* my = mysql_init(NULL);
    if(my == nullptr)
    {
        cerr << "mysql init error!" << endl;
        exit(1);
    }
    cout << "mysql init success!" << endl;
    if(mysql_real_connect(my, Host.c_str(), User.c_str(), Passwd.c_str(), Db.c_str(), Port, nullptr, 0) ==nullptr)
    {
        cerr << "mysql connect error!" << endl;
        exit(2);
    }
    cout << "mysql connect success!" << endl;
    const char* sql = "insert into t1 values(18,'xiaogao','男')";
    int n = mysql_query(my, sql);
    if(n != 0)
    {
        cout << "mysql query error!" << endl;
        exit(3);
    }
    cout << "mysql query success!" << endl;
    mysql_close(my);
    cout << "mysql close success!" << endl;    
    return 0;
}

  我们再来看插入的结果,如下图:

  通过上图可以看到,连接成功了但是下达指令失败了。我们检查了语法并没有错误,那是什么原因呢?注意:我们使用的语言插入数据时,还需要设置客户端与服务器之间的字符集。设置字符集函数原型如下:

int mysql_set_character_set(MYSQL *mysql, const char *charset)

参数说明:

  • mysql:已初始化的MYSQL结构体指针,表示与MySQL服务器的连接。
  • charset:一个字符串,表示要设置的字符集名称。

返回值:

  • 设置成功返回0,否则返回非零值。

  我们知道,远端的mysql的字符集时utf8,那么在来接成功后设置一下字符集即可。代码如下:

mysql_set_character_set(my, "utf8");

  我们再次进行插入,如下图:

  我们看到,现在就可以插入成功了。再看一下数据是否插入到对应的表中,如下图:

  其实删除和更新的sql语句都与插入语句相同,直接以字符串形式传递给mysql_query()函数。但是我们想查询呢?同时还需要获取查询结果该怎么办呢?

  mysql_store_result 函数用于将查询结果保存在一个客户端可访问的缓冲区中。它用于处理从数据库中检索的结果集。函数原型如下:

MYSQL_RES* mysql_store_result(MYSQL *mysql);

  参数说明:

  • mysql:一个指向MYSQL结构体的指针,表示与MySQL服务器的连接。

  返回值:

  • 成功时,返回一个指向MYSQL_RES结构体的指针,表示查询结果集。
  • 失败时,返回NULL。

  使用mysql_store_result函数的具体步骤如下:

  1. 在执行查询语句后,调用mysql_store_result函数来获取查询结果集。
  2. 判断返回值是否为NULL,如果为NULL,则表示查询出错。
  3. 通过返回的MYSQL_RES指针,可以使用其他函数来获取和处理结果集的数据。

  MYSQL_RES变量中保存了查询得到的各种信息,其类型定义如下:

typedef struct st_mysql_res {
	my_ulonglong  row_count;
	MYSQL_FIELD	*fields;
	MYSQL_DATA	*data;
	MYSQL_ROWS	*data_cursor;
	unsigned long *lengths;		/* column lengths of current row */
	MYSQL		*handle;		/* for unbuffered reads */
    const struct st_mysql_methods *methods;
    MYSQL_ROW	row;			/* If unbuffered read */
    MYSQL_ROW	current_row;		/* buffer to current row */
    MEM_ROOT	field_alloc;
    unsigned int	field_count, current_field;
    my_bool	eof;			/* Used by mysql_fetch_row */
    /* mysql_stmt_close() had to cancel this result */
    my_bool       unbuffered_fetch_cancelled;
    void *extension;
} MYSQL_RES;

  我们知道查询的结果会保存在MYSQL_RES变量中,但是怎么提取其中的数据呢?我们知道在MySQL中查询的结果是一张二维表,如下图:

  那么我们首先要做的就是获取表中数据的行数和列数。其函数原型如下:

//获取查询结果的行数
my_ulonglong mysql_num_rows(MYSQL_RES *res);

//获取查询结果的列数
unsigned int mysql_num_fields(MYSQL_RES *res);
  •   mysql_num_fields函数是一个用于获取结果集中字段(列)的数量的MySQL函数。它的作用是返回一个结果集中字段的数量,可以用于确定查询结果集中有多少列。
  •   mysql_num_fields函数的返回值是一个整数,表示结果集中的字段数量。如果发生错误或结果集为空,则返回0。
  •   mysql_num_rows函数是一个用于获取结果集中行的数量的MySQL函数。它的作用是返回一个结果集中行的数量,可以用于确定查询结果集中有多少行数据。
  •   mysql_num_rows函数的返回值是一个整数,表示结果集中的行数量。如果发生错误或结果集为空,则返回0。

  这两个函数的参数均是mysql_store_result 函数的返回值。也就是我们所获取的查询结果集。只有行数和列数不够,我们还需要能够获取其中的内容,我们再来看一个函数,函数原型如下:

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

参数解释:

  • resultMYSQL_RES 结构体指针,表示查询结果集。

返回值:

  • MYSQL_ROW:结果集中下一行的数据,以字符串数组的形式返回。如果已经读取完所有行,则返回NULL。

  实际上MYSQL_ROW就是一个char**的类型,其类型定义如下:

typedef char **MYSQL_ROW;		/* return data as array of strings */

  mysql_fetch_row函数也很像迭代器,当我们查找一行数据后,mysql_fetch_row会自动的向后移动一行,并不需要使用者自己去操作关心。接下来我们看一个查询的实例,具体代码如下:

#include <iostream>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <cstring>
#include <mysql/mysql.h>

using namespace std;

const string Host = "127.0.0.1";
const string User = "gtm";
const string Passwd = "gao520918";
const string Db = "test";
unsigned int Port = 3306;

int main()
{
    MYSQL* my = mysql_init(NULL);
    if(my == nullptr)
    {
        cerr << "mysql init error!" << endl;
        exit(1);
    }
    cout << "mysql init success!" << endl;
    if(mysql_real_connect(my, Host.c_str(), User.c_str(), Passwd.c_str(), Db.c_str(), Port, nullptr, 0) ==nullptr)
    {
        cerr << "mysql connect error!" << endl;
        exit(2);
    }
    cout << "mysql connect success!" << endl;
    mysql_set_character_set(my, "utf8");
    const char* sql = "select * from t1";
    int n = mysql_query(my, sql);

    int n = mysql_query(my, sql);
    if(n != 0)
    {
        cout << "mysql query error!" << endl;
        exit(3);
    }
    cout << "mysql query success!" << endl;

    MYSQL_RES* res = mysql_store_result(my);
    int row = mysql_num_rows(res);
    int col = mysql_num_fields(res);

    for(int i = 0; i < row; i++)
    {
        MYSQL_ROW line = mysql_fetch_row(res);
        for(int j = 0; j < col; j++)
        {
            cout << line[j] << "\t";
        }
        cout << endl;
    }
    mysql_free_result(res);
    mysql_close(my);
    cout << "mysql close success!" << endl;    
    return 0;
}

  运行结果如下图:

  但是上述获取行信息中,并没有获取到列的名字。看起来并不完整,我们在看如下函数:

MYSQL_FIELD* mysql_fetch_fields(MYSQL_RES *res);

 参数:

  • res:一个指向MYSQL_RES类型的结果集指针。该结果集通常通过调用mysql_store_result()mysql_use_result()函数从MySQL服务器获得。

  返回值:

  • 如果成功,返回一个指向MYSQL_FIELD结构体数组的指针,其中每个元素代表结果集的一个字段。
  • 如果失败,返回NULL。

  mysql_fetch_fields函数返回一个指向MYSQL_FIELD结构体数组的指针。MYSQL_FIELD结构体包含每个列相关字段的详细信息,如字段名、字段类型、字段长度等。结构体具体内容如下:

typedef struct st_mysql_field {
	char *name;                 /* Name of column */
	char *org_name;             /* Original column name, if an alias */
	char *table;                /* Table of column if column was a field */
	char *org_table;            /* Org table name, if table was an alias */
	char *db;                   /* Database for table */
	char *catalog;	      /* Catalog for table */
	char *def;                  /* Default value (set by mysql_list_fields) */
	unsigned long length;       /* Width of column (create length) */
	unsigned long max_length;   /* Max width for selected set */
	unsigned int name_length;
	unsigned int org_name_length;
	unsigned int table_length;
	unsigned int org_table_length;
	unsigned int db_length;
	unsigned int catalog_length;
	unsigned int def_length;
	unsigned int flags;         /* Div flags */
	unsigned int decimals;      /* Number of decimals in field */
	unsigned int charsetnr;     /* Character set */
	enum enum_field_types type; /* Type of field. See mysql_com.h for types */
	void *extension;
} MYSQL_FIELD;

  其用法也相当简单,我们获取到了列数,那么就可以直接打印即可,用法如下:

    MYSQL_FIELD* fields = mysql_fetch_fields(res);
    for(int i = 0; i < col; i++)
    {
        cout << fields[i].name << "\t\t";
    }
    cout << endl;

  我们再来看一下运行结果,如下图;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1331919.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker笔记2-docker 容器

docker 容器的运行 docker run 镜像名&#xff1a;版本标签&#xff1a; 创建 启动容器 docker run 镜像名 &#xff0c;如果镜像不存在&#xff0c;则会在线下载镜像。 注意事项&#xff1a; 容器内的进程必须处于前台运行状态&#xff0c;不能后台&#xff08;守护进程运行…

Android UID相关知识

一、UID/PID/GID/GIDS的含义和作用 UID : android中uid用于标识一个应用程序&#xff0c;uid在应用安装时被分配&#xff0c;并且在应用存在于手机上期间&#xff0c;都不会改变。一个应用程序只能有一个uid&#xff0c;多个应用可以使用sharedUserId 方式共享同一个uid&#…

【四】【C语言\动态规划】地下城游戏、按摩师、打家劫舍 II,三道题目深度解析

动态规划 动态规划就像是解决问题的一种策略&#xff0c;它可以帮助我们更高效地找到问题的解决方案。这个策略的核心思想就是将问题分解为一系列的小问题&#xff0c;并将每个小问题的解保存起来。这样&#xff0c;当我们需要解决原始问题的时候&#xff0c;我们就可以直接利…

YOLOv8改进 | 主干篇 | 利用SENetV1改进网络结构 (ILSVRC冠军得主)

一、本文介绍 本文给大家带来的改进机制是SENet&#xff08;Squeeze-and-Excitation Networks&#xff09;其是一种通过调整卷积网络中的通道关系来提升性能的网络结构。SENet并不是一个独立的网络模型&#xff0c;而是一个可以和现有的任何一个模型相结合的模块(可以看作是一…

Linux 宝塔mysql莫名其妙数据库不见了恢复数据库

起因&#xff1a;宝塔安装的mysql 线上运行突然表包括库都不见了&#xff0c;想办法恢复数据库 登陆mysql cd /www/server/mysql/binmysql -u root -p查看binlog日志是否打开 show variables like log_%;log_bin如果为 ON 则为开启状态&#xff0c;如果开启了才可以进行下一…

研究论文 2022-Oncoimmunology:AI+癌RNA-seq数据 识别细胞景观

Wang, Xin, et al. "Deep learning using bulk RNA-seq data expands cell landscape identification in tumor microenvironment." Oncoimmunology 11.1 (2022): 2043662. https://www.tandfonline.com/doi/full/10.1080/2162402X.2022.2043662 被引次数&#xff1…

哈希拓展攻击CTF题做法

目录 基础&#xff1a; 盐&#xff08;Salt&#xff09;&#xff1a; 哈希长度拓展攻击&#xff1a; kali下载相关工具hash-ext-attack&#xff1a; hash拓展题目特征&#xff1a; 哈希拓展ctf题&#xff1a; 2023楚慧杯upload_shell 实验吧之让我进去&#xff1a; 前言…

关于“Python”的核心知识点整理大全38

14.1.1 创建 Button 类 由于Pygame没有内置创建按钮的方法&#xff0c;我们创建一个Button类&#xff0c;用于创建带标签的实心矩形。 你可以在游戏中使用这些代码来创建任何按钮。下面是Button类的第一部分&#xff0c;请将这个类保存为 文件button.py&#xff1a; button.py …

渗透实验 XSS和SQL注入(Lab3.0)

windows server2003IIS搭建 配置2003的虚拟机 1、利用AWVS扫描留言簿网站&#xff08;安装见参考文档0.AWVS安装与使用.docx&#xff09;&#xff0c;发现其存在XSS漏洞&#xff0c;截图。 2、 Kali使用beef生成恶意代码 cd /usr/share/beef-xss./beef执行上面两条命令 …

Maven核心概念

1 Maven工程的GAVP Maven 中的 GAVP 是指 GroupId、ArtifactId、Version、Packaging 等四个属性的缩写&#xff0c;其中前三个是必要的&#xff0c;而 Packaging 属性为可选项。 这四个属性主要为每个项目在maven仓库中做一个标识&#xff0c;方便项目之间相互引用。 GAV G 即…

模式识别与机器学习(八):决策树

1.原理 决策树&#xff08;Decision Tree&#xff09;&#xff0c;它是一种以树形数据结构来展示决策规则和分类结果的模型&#xff0c;作为一种归纳学习算法&#xff0c;其重点是将看似无序、杂乱的已知数据&#xff0c;通过某种技术手段将它们转化成可以预测未知数据的树状模…

使用vue-qr,报错in ./node_modules/vue-qr/dist/vue-qr.js

找到node_modules—>vue-qr/dist/vue-qr.js文件&#xff0c;搜…e,将…去掉&#xff0c;然后重新运行项目。

【RabbitMQ】RabbitMQ详解(二)

RabbitMQ详解 死信队列死信来源消息TTL过期队列达到最大长度消息被拒绝 RabbitMQ延迟队列TTL的两种设置队列设置TTL消息设置TTL 整合SrpingBoot队列TTL延时队列TTL优化Rabbtimq插件实现延迟队列 死信队列 先从概念解释上搞清楚这个定义&#xff0c;死信&#xff0c;顾名思义就…

使用keytool查看Android APK签名

文章目录 一、找到JDK位置二、使用方法2.1 打开windows命令行工具2.2 查看签名 三、如何给APK做系统签名呢? 一、找到JDK位置 安卓AS之后&#xff0c;可选择继续安装JDK&#xff0c;如本文使用amazon版本默认位置&#xff1a;C:\Users\66176.jdks\corretto-1.8.0_342可通过自…

数据预处理:多重共线性_检测和解决办法

文章目录 1.多重共线性简介&#xff08;Collinearity and Multicollinearity&#xff09;1.1 多重共线性的后果1.2 处理多重共线性问题的方法 2. 设置2.1 导入库2.2 数据集特征波士顿房价BMI 数据集 2.3 导入数据 3. 相关矩阵3.1 聚类图 4. 方差膨胀因子4.1 两种多重共线性4.2 …

HackTheBox - Medium - Linux - Format

Format Format 是一种中等难度的 Linux 机器&#xff0c;它突出显示了由解决方案的结构方式引起的安全问题。立足点涉及PHP源代码审查&#xff0c;发现和利用本地文件读/写漏洞&#xff0c;并利用Nginx中的错误配置在Redis Unix套接字上执行命令。横向移动包括浏览 Redis 数据…

指针的含义

我们还取前面图片解释的道理&#xff1a; pa表示的意思就是这个地址&#xff0c;并不会显示出10这个数字 *pa就是指针&#xff0c;最后指向了a10&#xff0c;所以他最后程序输出是10 &pa这个含义就是取pa的地址&#xff0c;那么pa是一个虚拟的地址&#xff0c;只是简单的…

7种常见的网络安全设备及其功能

网络安全设备在现代网络环境中起着至关重要的作用&#xff0c;帮助保护个人和组织免受恶意攻击。本文将介绍7种常见的网络安全设备&#xff0c;包括防火墙、入侵检测系统、反病毒软件、数据加密设备、虚拟私人网络、安全信息和事件管理系统以及网络访问控制设备&#xff0c;并详…

Apache RocketMQ,构建云原生统一消息引擎

本文整理于 2023 年云栖大会林清山带来的主题演讲《Apache RocketMQ 云原生统一消息引擎》 演讲嘉宾&#xff1a; 林清山&#xff08;花名&#xff1a;隆基&#xff09;&#xff0c;Apache RocketMQ 联合创始人&#xff0c;阿里云资深技术专家&#xff0c;阿里云消息产品线负…

postgresql vacuum流程分析

概述 VACUUM是postgresql MVCC机制不可分割的组成部分。 postgresql在管理同一个元组的多个版本时&#xff0c;采取在堆表页面上从老版本到新版本放置元组的方法&#xff0c;每个元组都记录了xmax和xmin用于判断其可见性。这样的好处是&#xff08;1&#xff09;在索引键没有…