-
InnoDB的一次更新事务是怎么实现的?cid:link_2图像识别技术原理?cid:link_3MySQL的行级锁锁的到底是什么?https://bbs.huaweicloud.com/forum/thread-0233171697074647018-1-1.htmlHiLens支持从SD卡启动吗?cid:link_0数据库如果发生了死锁,该如何解决?cid:link_1为什么AI GALLERY里的模型不能直接用来部署呢cid:link_4mysql在InnoDB引擎下加索引,这个时候会锁表吗?cid:link_5图像识别技术原理cid:link_3
-
技术干货 数据库常见的死锁cid:link_0 MySQL中操作同一条记录的死锁问题及解决cid:link_1 数据库走索引但查询仍很慢所造成的一些原因cid:link_2 mysql中常见的减少回表增加查询性能的方法cid:link_11 InnoDB的一次更新事务的背后cid:link_12 MySQL的行级锁小知识点cid:link_13 MySQL 中常见的当前读和快照读cid:link_3 华为云 GaussDB 管理平台(TPoPS)页面实时告警推送方法总结cid:link_4 quartz用GaussDB的getJobDetail方法报错“For input string: "\x"常见解决方法cid:link_14 开发者空间的ubuntu系统安装dockercid:link_5 GAUSSDB根据实际业务负载动态优化数据分片策略cid:link_15 GaussDB分布式环境下保证分布式事务ACID属性主要方式cid:link_6 使用MySQL全文索引(Full-text Index)笔记cid:link_7 实现MySQL多主复制的几种常见方法cid:link_8 MySQL的查询缓存笔记分享cid:link_9 MySQL数据库常见的实现数据备份与恢复cid:link_16 MySQL主从复制cid:link_17 MySQL 处理外键约束cid:link_18 如何设计高效的数据库索引策略cid:link_10
-
设计高效的数据库索引策略需要综合考虑多个因素,包括索引类型的选择、索引键的顺序、查询模式、索引维护以及性能监控等。以下是一些关键的设计原则和优化策略:1. 选择合适的索引类型根据具体的查询需求和数据特征选择合适的索引类型:B树索引:适用于范围查询、排序操作和精确匹配。哈希索引:适用于等值查询,但不支持范围查询。全文索引:适用于文本数据的模糊匹配和全文搜索。空间索引:适用于地理空间数据的查询。2. 合理规划索引键顺序在创建复合索引时,将最常用于过滤条件的列放在索引的最前面,以减少索引扫描的数据量。同时,考虑查询中WHERE子句的列过滤频率以及是否涉及排序(ORDER BY)和分组(GROUP BY),调整这些列在索引中的位置。3. 考虑查询模式了解应用的查询模式对设计高效索引至关重要。对于经常作为查询条件的字段应优先建立索引。如果某些列经常一起出现在查询中,应该考虑为这些列创建复合索引。同时,考虑数据的更新模式,频繁更新的列可能不适合索引,因为索引会增加数据更新的开销。4. 索引维护与性能监控定期维护索引,避免索引碎片化。随着数据的增加,索引可能会变得碎片化,这时需要定期地重建或重新整理索引。同时,实施索引性能监控计划,识别不再使用或者效率低下的索引,根据监控结果调整现有索引策略,从而持续优化数据库性能。5. 平衡索引带来的益处和开销索引虽然能改善查询性能,但也会增加写操作的负担,占用更多的存储空间。在设计索引策略时,需要在查询优化和资源消耗之间找到合适的平衡点。评估索引带来的性能提升是否值得,以及这种性能提升是否符合业务的需求。避免创建过多的索引,因为过多的索引会消耗更多的磁盘空间,并且在插入、更新和删除操作时需要更多的时间来维护这些索引。6. 其他优化策略使用覆盖索引:当查询只需要索引中的数据列时,可以使用覆盖索引,避免访问实际数据行,从而提高查询效率。避免在索引列上使用函数或表达式:这会导致数据库无法使用索引,而是进行全表扫描,降低查询性能。适度设置索引列:设置索引时要考虑设置合适的列,不要造成“过多的索引列”。因为每个索引需要额外的磁盘空间,并降低写操作的性能。尽量使用前缀索引:对于长文本字段或者BLOB/TEXT类型的列,可以考虑只索引一部分前缀,以节省索引空间并提高查询效率。
-
MySQL的查询缓存(Query Cache)工作原理如下:查询缓存的存储结构查询缓存是一个内存区域,用于存储最近执行过的查询及其结果。它使用哈希表来存储查询缓存,键是查询的哈希值,值是查询的结果。哈希值是通过对查询字符串进行哈希计算得到的。查询缓存的命中条件查询必须完全相同:包括大小写、空格和注释。例如,“SELECT * FROM users”和“select * from users”是不同的查询。查询必须是SELECT语句:只有SELECT语句的结果会被缓存,其他如INSERT、UPDATE、DELETE等操作不会被缓存。查询中不能包含函数或子查询:例如,“SELECT COUNT(*) FROM users”不会被缓存,因为它包含了函数。查询中不能包含临时表或视图:例如,“SELECT * FROM (SELECT * FROM users) AS temp”不会被缓存。查询中不能包含用户变量:例如,“SET @id = 1; SELECT * FROM users WHERE id = @id”不会被缓存。查询缓存的工作流程查询请求:用户向MySQL服务器发出一条SELECT查询请求。查询缓存检查:MySQL首先会检查查询缓存,看看这条查询是否已经被缓存过。这里的检查是基于查询的文本内容,所以查询语句必须完全相同,包括大小写和空格。缓存命中:如果查询缓存中存在这条查询的结果,MySQL就会直接返回缓存中的结果给用户。这就叫做缓存命中(Cache Hit)。此时,MySQL不会再去执行查询语句。缓存未命中:如果查询缓存中没有这条查询的结果,MySQL就会执行SQL语句,去数据库中获取结果。然后,MySQL会把这次查询结果存入查询缓存中,供下次使用。这叫做缓存未命中(Cache Miss)。查询缓存的失效表被修改:当数据库中的数据发生变化,比如INSERT、UPDATE、DELETE操作,会影响到已经缓存的查询结果。此时,MySQL会自动将受影响的缓存条目清除,以保证数据的一致性。查询缓存被刷新:可以通过执行“FLUSH QUERY CACHE”语句来刷新查询缓存,这会清除所有缓存的查询结果。查询缓存被禁用:可以通过修改“query_cache_type”参数来禁用查询缓存,这会导致所有缓存的查询结果失效。
-
以下是实现MySQL多主复制的几种常见方法:基于传统复制的多主一从配置配置主库:在每个主库的配置文件(如my.cnf)中,确保server-id唯一,开启binlog日志(设置log-bin参数),并设置binlog_format为row。创建复制用户并授权:在每个主库上创建用于复制的用户,并授予REPLICATION SLAVE权限。配置从库:在从库的配置文件中,设置server-id,开启binlog日志(如果使用GTID模式),并设置binlog_format为row。设置从库连接主库:在从库上执行CHANGE MASTER TO命令,指定每个主库的连接信息,如master_host、master_user、master_password、master_port、master_log_file和master_log_pos。启动从库复制:在从库上执行START SLAVE命令,启动复制进程。检查复制状态:在从库上执行SHOW SLAVE STATUS命令,确保Slave_IO_Running和Slave_SQL_Running状态为Yes。使用GTID模式实现多主复制配置主库:在每个主库的配置文件中,开启GTID模式(设置gtid_mode=on,enforce_gtid_consistency=1),并设置binlog_format为row。创建复制用户并授权:在每个主库上创建用于复制的用户,并授予REPLICATION SLAVE权限。配置从库:在从库的配置文件中,开启GTID模式,设置binlog_format为row。设置从库连接主库:在从库上执行CHANGE MASTER TO命令,指定每个主库的连接信息,如master_host、master_user、master_password、master_port和MASTER_AUTO_POSITION=1。启动从库复制:在从库上执行START SLAVE命令,启动复制进程。检查复制状态:在从库上执行SHOW SLAVE STATUS命令,确保Slave_IO_Running和Slave_SQL_Running状态为Yes。使用MySQL Group Replication(MGR)实现多主复制配置MGR集群:在每个节点的配置文件中,设置server-id,开启binlog日志,设置binlog_format为row,并配置MGR相关参数,如group_replication_group_name、group_replication_local_address和group_replication_group_seeds。启动MGR集群:在每个节点上启动MySQL服务,并执行SET GLOBAL group_replication_bootstrap_group=ON;和START GROUP_REPLICATION;命令,启动MGR集群。检查集群状态:在任意节点上执行SELECT * FROM performance_schema.replication_group_members;命令,检查集群成员状态。使用中间件实现多主复制配置主库和从库:按照传统复制或GTID模式的要求,配置好每个主库和从库。部署中间件:选择合适的中间件,如MySQL Router、MaxScale等,并按照其官方文档进行安装和配置。配置中间件连接主库和从库:在中间件中配置主库和从库的连接信息,设置读写分离规则等。启动中间件:启动中间件服务,使其开始工作。测试和优化:通过测试工具或实际应用场景,对多主复制环境进行测试,根据测试结果进行优化和调整。
-
MYSQlvarchar转为mediumtextALTER TABLE table_name MODIFY COLUMN column_name mediumtext; ALTER TABLE table_name MODIFY COLUMN column_name varchar(255) 1. 修改字段的数据类型使用 MODIFY COLUMN 可以改变字段的数据类型、长度、默认值或注释,但不会更改字段名称。ALTER TABLE table_name MODIFY COLUMN column_name new_data_type [constraint];示例:将 age 字段的数据类型从 INT(4) 修改为 TINYINT(3)。ALTER TABLE employees MODIFY COLUMN age TINYINT(3) NOT NULL COMMENT '年龄';2. 修改字段的名称及属性使用 CHANGE COLUMN 可以同时更改字段名称及其属性。ALTER TABLE table_name CHANGE old_column_name new_column_name new_data_type [constraint];示例:将 name 字段重命名为 student_name,并将其数据类型改为 VARCHAR(100)。ALTER TABLE students CHANGE name student_name VARCHAR(100) NOT NULL COMMENT '学生姓名';3. 修改字段的默认值可以通过 MODIFY COLUMN 或 CHANGE COLUMN 来修改字段的默认值。ALTER TABLE table_name MODIFY COLUMN column_name data_type DEFAULT default_value;示例:将 salary 字段的默认值设置为 0。ALTER TABLE employees MODIFY COLUMN salary DECIMAL(10, 2) DEFAULT 0;4. 添加或删除字段的非空约束添加非空约束:ALTER TABLE table_name MODIFY COLUMN column_name data_type NOT NULL;示例:将 name 字段设置为非空。ALTER TABLE employees MODIFY COLUMN name VARCHAR(50) NOT NULL;删除非空约束:ALTER TABLE table_name MODIFY COLUMN column_name data_type NULL;示例:将 name 字段设置为可空。ALTER TABLE employees MODIFY COLUMN name VARCHAR(50) NULL;ORACLENVARCHAR2 转为NCLOB新增临时字段为NCLOBALTER TABLE COMMON_DATA_AUTOMATIC_CONFIG ADD TEMP CLOB;将需要修改的字段的值设置给临时字段UPDATE COMMON_DATA_AUTOMATIC_CONFIG SET TEMP = PARAMETERS_VALUE;删除需要修改的字段ALTER TABLE COMMON_DATA_AUTOMATIC_CONFIG DROP COLUMN PARAMETERS_VALUE;修改临时字段的名字为需要修改字段名ALTER TABLE COMMON_DATA_AUTOMATIC_CONFIG RENAME COLUMN TEMP to PARAMETERS_VALUE;1. 重命名列ALTER TABLE table_name RENAME COLUMN old_column_name TO new_column_name;示例:ALTER TABLE employees RENAME COLUMN first_name TO given_name;2. 修改列的数据类型ALTER TABLE table_name MODIFY (column_name datatype);示例:ALTER TABLE employees MODIFY (salary NUMBER(10, 2));3. 添加新列ALTER TABLE table_name ADD column_name datatype;示例:ALTER TABLE employees ADD bonus NUMBER(10, 2);4. 删除列ALTER TABLE table_name DROP COLUMN column_name;示例:ALTER TABLE employees DROP COLUMN bonus;5. 修改列的默认值ALTER TABLE table_name MODIFY (column_name datatype DEFAULT default_value);示例:ALTER TABLE employees MODIFY (hire_date DATE DEFAULT SYSDATE);6. 修改列的约束a. 添加约束ALTER TABLE table_name ADD CONSTRAINT constraint_name condition;示例:ALTER TABLE employees ADD CONSTRAINT chk_salary CHECK (salary > 0);b. 删除约束ALTER TABLE table_name DROP CONSTRAINT constraint_name;示例:ALTER TABLE employees DROP CONSTRAINT chk_salary; KESvarchar转为textALTER TABLE common_data_automatic_config MODIFY COLUMN parameters_value TEXT1. 修改字段的数据类型使用 ALTER TABLE 语句修改列的数据类型:ALTER TABLE table_name MODIFY COLUMN column_name new_data_type;例如,将 name 列的数据类型从 VARCHAR2(50) 改为 NCLOB:ALTER TABLE example_table MODIFY COLUMN name NCLOB;2. 修改字段的默认值使用 ALTER TABLE 语句修改列的默认值:ALTER TABLE table_name MODIFY COLUMN column_name DEFAULT default_value;例如,将 salary 列的默认值设置为 0:ALTER TABLE employees MODIFY COLUMN salary DEFAULT 0;3. 删除字段的默认值如果需要删除字段的默认值,可以使用以下命令:ALTER TABLE table_name MODIFY COLUMN column_name DEFAULT NULL;例如,将 salary 列的默认值设置为 NULL:ALTER TABLE employees MODIFY COLUMN salary DEFAULT NULL;4. 修改字段的非空约束添加或删除字段的非空约束:添加非空约束:ALTER TABLE table_name MODIFY COLUMN column_name NOT NULL;例如,将 name 列设置为非空:ALTER TABLE employees MODIFY COLUMN name NOT NULL;删除非空约束:ALTER TABLE table_name MODIFY COLUMN column_name NULL;例如,将 name 列设置为可空:ALTER TABLE employees MODIFY COLUMN name NULL;5. 重命名字段使用 RENAME COLUMN 子句重命名字段:ALTER TABLE table_name RENAME COLUMN old_column_name TO new_column_name;例如,将 name 列重命名为 full_name:ALTER TABLE employees RENAME COLUMN name TO full_name;6. 添加新列使用 ADD 子句添加新的列:ALTER TABLE table_name ADD column_name data_type [constraint];例如,添加一个名为 birthdate 的日期列:ALTER TABLE employees ADD birthdate DATE;7. 删除列使用 DROP COLUMN 子句删除列:ALTER TABLE table_name DROP COLUMN column_name;例如,删除 address 列:ALTER TABLE employees DROP COLUMN address;———————————————— 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 原文链接:https://blog.csdn.net/jg_csdn/article/details/144824850
-
CONCAT(str1, str2, ...)将多个字符串值连接成一个字符串。SELECT CONCAT('Hello, ', 'World!'); -- 结果: 'Hello, World!'LENGTH(str)返回字符串的长度(字节数)。SELECT LENGTH('Hello, World!'); -- 结果: 13CHAR_LENGTH(str)返回字符串的字符数。SELECT CHAR_LENGTH('Hello, World!'); -- 结果: 13SUBSTRING(str, pos, len)从字符串 str 中提取从位置 pos 开始的 len 长度的子字符串。如果不指定 len,则提取到字符串的末尾。SELECT SUBSTRING('Hello, World!', 8, 5); -- 结果: 'World'LOWER(str)将字符串中的所有字符转换为小写。SELECT LOWER('Hello, World!'); -- 结果: 'hello, world!'UPPER(str)将字符串中的所有字符转换为大写。SELECT UPPER('Hello, World!'); -- 结果: 'HELLO, WORLD!'TRIM(str)去除字符串两端的空白字符。SELECT TRIM(' Hello, World! '); -- 结果: 'Hello, World!'REPLACE(str, from_str, to_str)将字符串 str 中的所有 from_str 替换为 to_str。SELECT REPLACE('Hello, World!', 'World', 'Everyone'); -- 结果: 'Hello, Everyone!'LEFT(str, len)返回字符串 str 最左边的 len 个字符。SELECT LEFT('Hello, World!', 5); -- 结果: 'Hello'RIGHT(str, len)返回字符串 str 最右边的 len 个字符。SELECT RIGHT('Hello, World!', 6); -- 结果: 'World!'请注意,这些函数的结果是基于示例字符串 'Hello, World!'。在实际的 MySQL 数据库中,你需要替换 'Hello, World!' 为你的列名或者实际的字符串值。在实际应用中,你可以直接在 SQL 查询中使用这些函数,例如:SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;这条查询将会连接 users 表中的 first_name 和 last_name 字段,并返回新的列 full_name。其他函数也可以以类似的方式在查询中使用,以满足特定的数据处理需求。———————————————— 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 原文链接:https://blog.csdn.net/hebtu666/article/details/139453652
-
一:🔥 MySQL connect📚 MySQL 的基础,我们之前已经学过,后面我们只关心使用要使用 C 语言连接 MySQL,需要使用 MySQL 官网提供的库,大家可以去官网下载我们使用 C接口库来进行连接要正确使用,我们需要做一些准备工作: 保证 mysql 服务有效在官网上下载合适自己平台的 MySQL connect 库,以备后用建议直接使用命令 sudo yum install -y mysql-community-server 安装🦋 Connector / C 使用📚 我们下下来的库格式如下:# tree /usr/include/mysql/usr/include/mysql├── client_plugin.h├── errmsg.h├── field_types.h├── my_command.h├── my_compress.h├── my_list.h├── mysql_com.h├── mysqld_error.h├── mysql.h├── mysql_time.h├── mysql_version.h├── mysqlx_ername.h├── mysqlx_error.h├── mysqlx_version.h├── plugin_auth_common.h└── udf_registration_types.h lib# find /usr -name "libmysqlclient*"/usr/share/doc/libmysqlclient21/usr/share/doc/libmysqlclient-dev/usr/lib/x86_64-linux-gnu/libmysqlclient.so.21.2.40/usr/lib/x86_64-linux-gnu/libmysqlclient.a/usr/lib/x86_64-linux-gnu/libmysqlclient.so/usr/lib/x86_64-linux-gnu/libmysqlclient.so.21 📚 其中 include 包含所有的方法声明, lib 包含所有的方法实现(打包成库) 尝试链接 mysql client 通过 mysql_get_client_info() 函数,来验证我们的引入是否成功 #include <iostream>#include <mysql/mysql.h> int main(){std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;return 0;} $ g++ -o mytest test.cc -std=c++11 -lmysqlclient$ lsMakefile mytest test.cc $ ./mytest mysql client version: 8.0.40 至此引入库的工作已经做完,接下来就是熟悉接口 🦋 mysql 接口介绍🦁 MySQL官方文档借口介绍 初始化 mysql_init()要使用库,必须先进行初始化! 初始化一个 MYSQL对象 MYSQL *mysql_init(MYSQL *mysql); 使用 mysql_init函数初始化一个 MySQL 连接句柄,为后续操作做准备。如: MYSQL *mfp = mysql_init(NULL) 链接数据库 mysql_real_connect📚 初始化完毕之后,必须先链接数据库,在进行后续操作。(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); //建立好链接之后,获取英文没有问题,如果获取中文是乱码://设置链接的默认字符集是utf8,原始默认是latin1mysql_set_character_set(myfd, "utf8"); 11第一个参数 MYSQL是 C api 中一个非常重要的对象(mysql_init的返回值),里面内存非常丰富,有port, dbname, charset 等连接基本参数。它也包含了一个叫 st_mysql_methods 的结构体变量,该变量里面保存着很多函数指针,这些函数指针将会在数据库连接成功以后的各种数据操作中被调用。mysql_real_connect 函数中各参数,基本都是顾名思意。 📚 测试: #include <iostream>#include <unistd.h>#include <string>#include <mysql/mysql.h> const std::string host = "127.0.0.1";const std::string user = "connector";const std::string passwd = "123456";const std::string db = "conn";const unsigned int port = 3306; int main(){ std::cout << "mysql client version: " << mysql_get_client_info() << std::endl; MYSQL* my = mysql_init(nullptr); if(my == nullptr) { std::cerr << "init MySQL error" << std::endl; return 1; } if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr) { std::cerr << "connect MYSQL error" << std::endl; return 2; } std::cout << "connect success" << std::endl; mysql_set_character_set(my, "utf8"); // 设置字符集 mysql_close(my); return 0;} 📚 结果: # ./mytest mysql client version: 8.0.40connect success123下发 mysql 命令 mysql_query int mysql_query(MYSQL *mysql, const char *q);1第一个参数上面已经介绍过,第二个参数为要执行的sql语句,如“select * from table”。获取执行结果 mysql_store_result sql 执行完以后,如果是查询语句,我们当然还要读取数据,如果 update,insert 等语句,那么就看下操作成功与否即可。 #include <iostream>#include <unistd.h>#include <string>#include <mysql/mysql.h> const std::string host = "127.0.0.1";const std::string user = "connector";const std::string passwd = "123456";const std::string db = "conn";const unsigned int port = 3306; int main(){ std::cout << "mysql client version: " << mysql_get_client_info() << std::endl; MYSQL* my = mysql_init(nullptr); if(my == nullptr) { std::cerr << "init MySQL error" << std::endl; return 1; } if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr) { std::cerr << "connect MYSQL error" << std::endl; return 2; } std::cout << "connect success" << std::endl; mysql_set_character_set(my, "utf8"); // 设置字符集 std::string sql; while(true) { std::cout << "MySQL>>> "; if(!std::getline(std::cin, sql) || sql == "quit") { std::cout << "bye bye" << std::endl; break; } int n = mysql_query(my, sql.c_str()); if(n == 0) { std::cout << sql << " success: " << n << std::endl; } else { std::cerr << sql << " failed" << n << std::endl; } } mysql_close(my); return 0;} 我们来看看如何获取查询结果: 如果 mysql_query 返回成功,那么我们就通过 mysql_store_result 这个函数来读取结果。原型如下: MYSQL_RES *mysql_store_result(MYSQL *mysql);1该函数会调用 MYSQL 变量中的 st_mysql_methods 中的 read_rows 函数指针来获取查询的结果。同时该函数会返回 MYSQL_RES 这样一个变量,该变量主要用于保存查询的结果。同时该函数 malloc 了一片内存空间来存储查询过来的数据,所以我们一定要记的 free(result), 不然是肯定会造成内存泄漏的。 执行完 mysql_store_result 以后,其实数据都已经在 MYSQL_RES 变量中了,下面的 api 基本就是读取 MYSQL_RES 中的数据。 获取结果行数 mysql_num_rows获取结果列数 mysql_num_fields获取列名 mysql_fetch_fields如: int fields = mysql_num_fields(res);MYSQL_FIELD *field = mysql_fetch_fields(res);for(int i = 0; i < fields; i++){cout<<field[i].name<<" ";} 获取结果内容mysql_fetch_row它会返回一个MYSQL_ROW变量,MYSQL_ROW其实就是char **. 就当成一个二维数组来用吧 MYSQL_ROW line;for(i = 0; i < nums; i++){line = mysql_fetch_row(res);for(int j = 0; j < fields; j++){cout << line[j] << " ";} } 🦋 完整代码样例#include <iostream>#include <unistd.h>#include <string>#include <mysql/mysql.h> const std::string host = "127.0.0.1";const std::string user = "connector";const std::string passwd = "123456";const std::string db = "conn";const unsigned int port = 3306; int main(){ std::cout << "mysql client version: " << mysql_get_client_info() << std::endl; MYSQL* my = mysql_init(nullptr); if(my == nullptr) { std::cerr << "init MySQL error" << std::endl; return 1; } if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr) { std::cerr << "connect MYSQL error" << std::endl; return 2; } std::cout << "connect success" << std::endl; mysql_set_character_set(my, "utf8"); // 设置字符集 //std::string sql = "update user set name='Jimmy' where id=2"; //std::string sql = "insert into user (name, age, telphone) values ('peter', 19, 6543219876)"; std::string sql = "select * from user"; int n = mysql_query(my, sql.c_str()); if(n == 0) std::cout << sql << " success" << std::endl; else { std::cerr << sql << " failed" << std::endl; return 3; } MYSQL_RES *res = mysql_store_result(my); if(res == nullptr) { std::cerr << "mysql_store_result error" << std::endl; return 4; } my_ulonglong rows = mysql_num_rows(res); my_ulonglong fields = mysql_num_fields(res); std::cout << "行: " << rows << std::endl; std::cout << "列: " << fields << std::endl; // 属性 MYSQL_FIELD *fields_array = mysql_fetch_fields(res); for(int i = 0; i < fields; i++) { std::cout << fields_array[i].name << '\t'; } std::cout << '\n'; // 内容 for(int i = 0; i < rows; i++) { MYSQL_ROW row = mysql_fetch_row(res); // mysql_fetch_row相当于一个迭代器,会自动向后遍历 MYSQL_ROW 就是一个 char** 的二级指针 for(int j = 0; j < fields; j++) { std::cout << row[j] << '\t'; } std::cout << '\n'; } mysql_free_result(res); mysql_close(my); return 0;} 81📚 关闭 mysql 链接 mysql_close void mysql_close(MYSQL *sock);1📚 另外,mysql C api 还支持事务等常用操作,大家下来自行了解: my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);my_bool STDCALL mysql_commit(MYSQL * mysql);my_bool STDCALL mysql_rollback(MYSQL * mysql);123或者直接通过query函数直接操作都可以 二:🔥 共勉以上就是我对 【MySQL】使用C语言链接 的理解,觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~😉———————————————— 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 原文链接:https://blog.csdn.net/weixin_50776420/article/details/145124247
-
一、视图视图就是相当于创建一个表,将查询到的结果集给存储起来。像使用复杂的多表查询查询到的结果集就不可以对结果集操作。而使用视图就可以。视图是⼀个虚拟的表,它是基于⼀个或多个基本表或其他视图的查询结果集。视图本⾝不存储数据,⽽是通过执⾏查询来动态⽣成数据。⽤⼾可以像操作普通表⼀样使⽤视图进⾏查询、更新和管理。视图本⾝并不占⽤物理存储空间,它仅仅是⼀个查询的逻辑表⽰,物理上它依赖于基础表中的数据。使用查询语句查询查询真实数据时可以拿到敏感信息,但是如果将视图传给其他人来查询就可以避免。1.1 创建视图create view 视图名 (视图列名可省略) as (查询结果);1创建视图时如果将列名省略,那么是由查询结果的列名作为视图列名,但是如果查询结果中列名有重复就会创建失败,需要采取给其起别名来解决。 1.2 数据修改影响对视图的操作就跟表操作一样。修改真实表的数据会影响视图。修改视图也会影响真实表。视图修改的条件:创建视图时不能使⽤聚合函数。创建视图时不能使⽤distinct。创建视图时不能使⽤group by和having子句。创建视图时不能使⽤union和union all联合查询语句。查询列表中不能使⽤⼦查询。在from⼦句中引⽤不可更新视图。1.3 删除视图drop view 视图名;11.4视图优点简单性:视图可以将复杂的查询封装成⼀个简单的查询。例如,针对⼀个复杂的多表连接查询,可以创建⼀个视图,⽤⼾只需查询视图⽽⽆需了解底层的复杂逻辑。安全性:通过视图,可以隐藏表中的敏感数据。例如,⼀个系统的⽤⼾表中,可以创建⼀个不包含密码列视图,普通⽤⼾只能访问这个视图,⽽不能访问原始表。逻辑数据独立性:视图提供了⼀种逻辑数据独⽴性,即使底层表结构发⽣变化,只需修改视图定义,⽽⽆需修改依赖视图的应⽤程序。使⽤到应⽤程序与数据库的解耦可读性:视图允许⽤⼾重命名列名,以增强数据可读性。二、用户和权限管理在我们练习中都是使用root用户,root用户权限很大且一个数据库只有一个,在实际应用中,用户权限大小至关重要,而且还要有多个用户。2.1查看当前的数据库拥有用户信息用户信息存储在系统库mysql中的user表里面。mysql库是系统库,我们不要对其修改。语法:use mysql;select host, user, authentication_string from user;12名词解释:host:允许登录的主机,相当于⽩名单,如果是localhost,表⽰只能从本机登陆。user:⽤⼾名。*_priv:⽤⼾拥有的权限,*表示多个单词,相当于通配符。authentication_string :加密后的⽤⼾密码2.2 创建用户语法:create user [IF NOT EXISTS] '用户名(区分⼤⼩写)'@'主机名' identified by '密码';1这样创建的用户没有任何权限。注意事项:如果不指定host_name相当于’user_name’@‘%’,%表⽰所有主机都可以连接到数据库,强烈建议不要这样设置,因为会导致严重的安全问题。用户名和主机名中间的@没包含在单引号’'只内。host_name可以通过⼦⽹掩码设置主机范围:◦ 198.0.0.0/255.0.0.0 :A段⽹络中的任意⼀台主机;◦ 198.51.0.0/255.255.0.0: 198.51 B段⽹络中的任意⼀台主机;◦ 198.51.100.0/255.255.255.0: 198.51.100 C段⽹络中的任意⼀台主机;◦ 198.51.100.1 :只包含特定IP地址的主机。从MySQL8.0.23开始,指定为IPv4地址的主机值可以使⽤CIDR表⽰法写⼊,例如198.51.100.44/24。允许在IP地址中使⽤%通配符,⽐如,主机值’%'匹配任何主机名, 198.51.100.% 匹配198.51.100 C段⽹络中的任何主机。MySQL8.0.35中已弃⽤,以后可能会删除。示例:添加⼀个名为ikun的新⽤⼾,允许从本机登录 create user 'bit'@'localhost' identified by '123456';12.3 修改密码语法:# 为指定⽤⼾设置密码 alter user '用户名(区分大小写)'@'主机名' identified by '新密码';# 为指定⽤⼾设置密码set password for '用户名(区分大小写)'@'主机名' = '新密码';# 为当前登录⽤⼾设置密码set password = '新密码';123456示例:以root⾝份登录,为’ikun’@'localhost’⽤⼾重置密码 ALTER USER 'bit'@'localhost' IDENTIFIED BY '987654';1以root⾝份登录,为’ikun’@'localhost’⽤⼾重置密码SET PASSWORD FOR 'bit'@'localhost' = '123456';1以ikun⽤⼾登录,修改当前登录⽤⼾的密码 SET PASSWORD = '111111';12.4 删除用户语法:drop user [if exists] '用户名(区分大小写)'@'主机名';1示例:删除用户’ikun’@‘192.168.1.1/24’drop user 'ikun'@'192.168.1.1/24';12.5 权限MySQL内置⽀持的权限列表如下:2.5.1 授权语法:grant priv_type[, priv_type ...] on priv_level to'user_name'@'host_name' [WITH GRANT OPTION];1名词解释:priv_type:根据类型,参考根据列表4.1中的Privilege列。priv_level:* | . | db_name.* | db_name.tbl_name | tbl_name,⽐如*.*表⽰所有数据库下的所有表。‘user_name’@‘host_name’:指定⽤⼾。[WITH GRANT OPTION]:可选,允许⽤⼾将⾃⼰的权限授权给其它⽤⼾。示例:为ikun@localhost⽤⼾授权于 java01 数据库的 select 权限。grant select on java01.* to 'ikun'@'localhost';12.5.2 回收权限语法:REVOKE [IF EXISTS] priv_type[, priv_type] ... ON priv_level FROM 'user_name'@'host_name' [, 'user_name'@'host_name'] ...1示例:回收ikun@localhost⽤⼾对于 java01 数据库的权限:REVOKE all on *.* from 'ikun'@'localhost';———————————————— 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 原文链接:https://blog.csdn.net/yj20040627/article/details/142442386
-
MySQL的行级锁是一种用于管理并发访问的机制,它允许事务对表中的特定行进行锁定,从而实现对这些行的独占访问。行级锁的主要目的是提高数据库的并发性能,减少锁争用,同时确保数据的一致性和完整性。行级锁的类型记录锁(Record Locks):记录锁是为某行记录加锁,封锁该行的索引记录。例如,当执行SELECT * FROM table WHERE id = 1 FOR UPDATE;时,id为1的记录行会被锁住。间隙锁(Gap Locks):间隙锁基于非唯一索引,锁定一段范围内的索引记录。例如,执行SELECT * FROM table WHERE id BETWEEN 1 AND 10 FOR UPDATE;时,所有在(1,10)区间内的记录行都会被锁住。临键锁(Next-Key Locks):临键锁是一种特殊的间隙锁,存在于非唯一索引中,锁定一段左开右闭的索引区间。例如,当根据非唯一索引列进行UPDATE操作时,InnoDB会获取该记录行的临键锁,并同时获取该记录行下一个区间的间隙锁。行级锁的工作原理基于索引实现:InnoDB中的行锁是基于索引实现的。如果某个加锁操作没有使用索引,那么该锁就会退化为表锁。锁住索引:行级锁实际上是通过锁住索引来实现的。例如,在辅助索引中,索引存储的是二级索引和主键的值,因此通过辅助索引锁定一行数据时,会通过主键值找到主键索引,并锁定。行级锁的使用场景高并发更新:适用于按索引条件高并发更新少量不同数据,同时又有并发查询的应用,例如OLTP系统。并发查询:在并发查询时,可以通过行级锁来确保数据的一致性和隔离性。行级锁的优缺点优点:提高并发性能,减少锁争用。支持更高的并发更新和查询。缺点:开销较大,加锁和解锁的过程相对较慢。如果使用不当,可能会导致死锁或锁升级。行级锁的注意事项索引的使用:确保查询使用了索引,否则行级锁可能会退化为表锁。锁的兼容性:共享锁和排他锁之间的兼容性需要注意,排他锁会阻止其他事务获取相同数据行上的共享锁和排他锁。意向锁:意向锁的存在是为了使得行锁和表锁能够共存,从而实现多粒度的锁机制。
-
内容总结主从复制与GTID模式:文章详细介绍了MySQL主从复制的多种实现方式,重点讲解了GTID模式如何简化主从同步配置和管理,提高数据库的容错性和可维护性。权限与安全管理:深入解析了MySQL的用户权限、组管理,以及行锁与表锁机制,帮助开发者更好地理解如何控制数据访问权限和并发控制。读写分离与性能优化:对比了代码层面的读写分离与使用ProxySQL工具进行自动化读写分离的优劣,强调了锁机制(临键锁、间隙锁、记录锁)对性能的影响。事务与隔离级别:讲解了MySQL的事务隔离级别,解释了不同隔离级别对并发控制和数据一致性的影响,提升了对事务管理的理解。索引与查询优化:探讨了B树和Hash索引的优缺点,并深入剖析了MySQL索引优化的技术,帮助提高查询效率。数据库引擎与数据结构:介绍了MyISAM与InnoDB引擎的区别,讨论了B+树、B树、红黑树等数据结构在数据库中的应用,提升了对数据存储和检索的理解。链接地址标题: 数据库同步革命:MySQL GTID模式下主从配置的全面解析链接: cid:link_5标题: 探秘MySQL主从复制的多种实现方式链接: cid:link_6标题: MySQL权限管理大揭秘:用户、组、权限解析链接: cid:link_7标题: 代码层面的读写分离vs使用proxysql链接: cid:link_8标题: 事务隔离大揭秘:MySQL中的四种隔离级别解析链接: cid:link_9标题: MySQL锁三部曲:临键、间隙与记录的奇妙旅程链接: cid:link_0标题: 数据安全之路:深入了解MySQL的行锁与表锁机制链接: cid:link_10标题: 索引大战:探秘InnoDB数据库中B树和Hash索引的优劣链接: cid:link_11标题: 树中枝繁叶茂:探索 B+ 树、B 树、二叉树、红黑树和跳表的世界链接: cid:link_12标题: 解谜MySQL索引:优化查询速度的不二法门链接: cid:link_1标题: MySQL Redo Log解密:事务故事的幕后英雄链接: cid:link_2标题: MySQL Binlog深度解析:进阶应用与实战技巧链接: cid:link_13标题: 解密MySQL中的临时表:探究临时表的神奇用途链接: cid:link_3标题: 深入解析MySQL 8中的角色与用户管理链接: cid:link_14标题: 解密MySQL二进制日志:深度探究mysqlbinlog工具链接: cid:link_15标题: MySQL引擎对决:深入解析MyISAM和InnoDB的区别链接: cid:link_4
-
数据库发生死锁时,可以采取以下方法解决:预防死锁破坏互斥条件:使资源可同时访问,但很多资源往往不能同时访问,所以这种方法在大多数场合行不通。破坏不可剥夺条件:采用剥夺式调度算法,目前一般仅适用于主存资源和处理器资源的分配,并不适用于所有资源,且会导致资源利用率下降。破坏持有等待条件:采用静态分配策略,一次性申请所有资源。进程要么占有所有资源然后开始执行,要么不占有资源,不会出现占有一些资源等待一些资源的情况。但这种策略严重降低了资源利用率。破坏环路等待条件:采用层次分配策略,将所有资源分成多个层次。一个进程得到某资源后只能申请较高一层的资源;一个资源释放资源只能先释放较高层的资源。按这种策略,不可能出现循环等待链。避免死锁允许系统中同时存在死锁产生的四个必要条件,只要掌握并发进程中与每个进程有关的资源动态申请情况,做出明智和合理的选择,仍然可以避免死锁。可以通过银行家算法来实现,当一个进程申请使用资源的时候,先试探分配给该进程资源,然后通过安全性算法判断分配后系统是否处于安全状态,若不安全则试探分配作废,让该进程继续等待,若能够进入到安全的状态,则就真的分配资源给该进程。检测死锁系统设有专门的机构,当死锁发生时,该机构能检测死锁发生并精确确定与死锁有关的进程和资源。可以通过查看数据库管理系统提供的相关视图或日志来检测死锁,例如在 MySQL 中,可以通过查看 information_schema.INNODB_TRX、INFORMATION_SCHEMA.INNODB_LOCKS 和 INFORMATION_SCHEMA.INNODB_LOCK_WAITS 等视图来了解当前的事务和锁等待情况,也可以通过查看错误日志或使用 SHOW ENGINE INNODB STATUS 命令来获取死锁相关的信息。在 SQL Server 中,可以查询 sys.dm_exec_requests 视图来查看当前的锁等待情况。解除死锁自动死锁回滚:利用数据库管理系统的自动死锁检测和回滚功能,及时解除死锁。例如,MySQL 的 InnoDB 存储引擎会定期运行死锁检测算法,一旦发现死锁,就会回滚其中一个事务以解除死锁。手动干预:通过监控系统视图,手动终止发生死锁的事务。可以先通过查询相关视图找到发生死锁的事务,然后使用数据库管理系统提供的命令来终止这些事务,例如在 MySQL 中,可以使用 KILL 命令来终止进程。抢占资源:从涉及死锁的一个或多个进程中抢占资源,把夺得的资源再分配给涉及死锁的进程直至死锁解除。撤销进程:逐个撤销涉及死锁的进程,回收资源直至死锁解除。优化事务设计减少事务大小:尽量将大事务拆分成多个小事务,减少事务的持续时间,从而减少持有锁的时间,降低与其他事务发生冲突的可能性。固定资源访问顺序:如果所有事务都按照相同的顺序访问资源,那么死锁的可能性就会大大降低。例如,如果有多个表或资源需要锁定,总是按照相同的顺序(如字典顺序)锁定这些资源。避免长时间的事务:尽量减少事务的执行时间,避免长时间占用锁。可以通过优化业务逻辑、减少不必要的操作或使用异步处理等方式来缩短事务的执行时间。调整隔离级别根据实际需求选择合适的隔离级别。例如,在可以接受幻读的情况下,使用读已提交(READ COMMITTED)隔离级别可以降低死锁的风险。但需要注意的是,降低隔离级别可能会引入其他并发问题,需要根据具体的业务场景进行权衡。监控和日志记录实施监控和日志记录来跟踪死锁和性能瓶颈。这可以帮助识别导致死锁的具体事务和操作,从而进行针对性的优化。可以通过数据库管理系统提供的性能监控工具或第三方监控工具来实时监控数据库的性能指标,包括死锁的发生频率和持续时间等。
-
数据库如果发生了死锁,该如何解决?
-
mysql中操作同一条记录会发生死锁吗?
-
走了索引,但是还是很慢是什么原因?
推荐直播
-
GaussDB管理平台TPOPS,DBA高效运维的一站式解决方案
2024/12/24 周二 16:30-18:00
Leo 华为云数据库DTSE技术布道师
数据库的复杂运维,是否让你感到头疼不已?今天,华为云GaussDB管理平台将彻底来改观!本期直播,我们将深入探索GaussDB管理平台的TPOPS功能,带你感受一键式部署安装的便捷,和智能化运维管理的高效,让复杂的运维、管理变得简单,让简单变得可靠。
回顾中 -
DTT年度收官盛典:华为开发者空间大咖汇,共探云端开发创新
2025/01/08 周三 16:30-18:00
Yawei 华为云开发工具和效率首席专家 Edwin 华为开发者空间产品总监
数字化转型进程持续加速,驱动着技术革新发展,华为开发者空间如何巧妙整合鸿蒙、昇腾、鲲鹏等核心资源,打破平台间的壁垒,实现跨平台协同?在科技迅猛发展的今天,开发者们如何迅速把握机遇,实现高效、创新的技术突破?DTT 年度收官盛典,将与大家共同探索华为开发者空间的创新奥秘。
回顾中
热门标签