Mysql删库跑路,如何恢复数据?

问题

      删库跑路,数据还能恢复吗?

       我们经常听说某某被领导训斥了,对领导心生痛恨,然后登录 Mysql 删库跑路。对于闲聊中经常听说过的一个段子,在现实生活中是否真的发生过,如果发生了,我们该如何解决,被删的数据还能恢复过来吗?

如何解决

        如果数据库所有的数据都删除了, 数据库没有备份,但所有的 binlog 日志都在的话,就可以使用 binlog 文件,从第一个开始逐个恢复每个 binlog 文件里的数据。但这种一般不会这么做,因为 binlog日志比较大,恢复起来比较耗时,而且 binlog 占用的磁盘空间也比较大,生产上都会定期删除的,所以一般不太可能使用 binlog 文件恢复整个数据库的。

        一般通用的做法是,每天凌晨后做一次全量数据库的备份,那么恢复数据库的时候,就可以使用最近一次全量备份再加上备份时间点后的 binlog 文件来恢复数据。

mysqldump备份数据库

        备份数据库我们一般使用 mysqldump 命令工具。

  • 备份所有的数据库

        语法:mysqldump -u[用户名] -p[密码] --all-databases > /备份路径/备份文件名.sql

#备份全部数据库
mysqldump -uroot -p123456 --all-databases > backup_all_databases.sql
  •  备份一个/多个数据库

        语法:mysqldump -u[用户名] -p[密码] --databases DB1 [DB2 DB3...]  > /备份路径/备份文件名.sql

#备份一个数据库
mysqldump -uroot -p123456 --databases database_test1 > backup_database_test1.sql#备份多个数据库
mysqldump -uroot -p123456 --databases database_test1 database_test2 > backup_database_test1_test2.sql
  • 备份指定库中的指定表

        语法:mysqldump -u[用户名] -p[密码] [database] [table1] [table2] > /备份路径/备份文件名.sql

#备份库中的部分表
mysqldump -uroot -p123456 database_test1 table_test1 table_test2 > backup_tables.sql

mysqldump恢复数据 

  • 恢复数据库

        备份所有数据库和备份指定库的恢复逻辑相同

        语法:mysql -u[用户名] -p[密码] < /备份文件路径/备份文件名.sql

#还原数据库
mysql -uroot -p123456 < backup_database_test1_test2.sql
  •  恢复数据表

        恢复表的前提是表所在的库必须存在,且可任意指定库进行恢复操作

        语法:mysqldump -u[用户名] -p[密码] [database]  < /备份文件路径/备份文件名.sql

mysql -u root -p123456 database_test1 < backup_tables.sql

        当使用全量备份数据恢复了备份的数据,然后接下来就用 binlog 文件来恢复还没备份的数据,比如每天凌晨1点钟全量备份数据库数据,然后14:00点钟,数据都被删除了,此时用全量数据线恢复,再用凌晨1点钟到下午14:00的binlog 文件恢复剩下的数据。接下来,就介绍 binlog 日志文件。

binlog二进制归档日志

        binlog 二级制日志记录保存了所有执行过的修改操作语句,但不保存查询操作,二进制日志的主要用途包括数据恢复、数据备份和复制。

        MySQL5.7 版本中,binlog默认是关闭的,8.0版本默认是打开的,打开binlog功能,需要修改配置文件my.ini(windows)或my.cnf(linux),然后重启数据库。

在配置文件中的[mysqld]部分增加如下配置:

# log-bin设置binlog的存放位置,可以是绝对路径,也可以是相对路径,这里写的相对路径,则binlog文件默认会放在data数据目录下
log-bin=mysql-binlog
# Server Id是数据库服务器id,随便写一个数都可以,这个id用来在mysql集群环境中标记唯一mysql服务器,集群环境中每台mysql服务器的id不能一样,不加启动会报错
server-id=1
# 其他配置
binlog_format = row # 日志文件格式,下面会详细解释
expire_logs_days = 15 # 执行自动删除距离当前15天以前的binlog日志文件的天数, 默认为0, 表示不自动删除
max_binlog_size = 200M # 单个binlog日志文件的大小限制,默认为 1GB

查看binlog相关参数 

show variables like '%log_bin%';

 查询结果

094153fd30b0492293915faeb2e8a86e.png

  • log_bin:binlog日志是否打开状态
  • log_bin_basename:是binlog日志的基本文件名,后面会追加标识来表示每一个文件,binlog日志文件会滚动增加
  • log_bin_index:指定的是binlog文件的索引文件,这个文件管理了所有的binlog文件的目录。
  • sql_log_bin:sql语句是否写入binlog文件,ON代表需要写入,OFF代表不需要写入。如果想在主库上执行一些操作,但不复制到slave库上,可以通过修改参数sql_log_bin来实现。比如说,模拟主从同步复制异常。

查看有多少binlog文件

show binary logs;

查询结果

7f20541bc464479e8ae71c53ca0574d1.png

 

binlog 的日志格式

用参数 binlog_format 可以设置binlog日志的记录格式,mysql支持三种格式类型:

  • STATEMENT:基于SQL语句的复制,每一条会修改数据的sql都会记录到master机器的bin-log中,这种方式日志量小,节约IO开销,提高性能,但是对于一些执行过程中才能确定结果的函数,比如UUID()、SYSDATE()等函数如果随sql同步到slave机器去执行,则结果跟master机器执行的不一样。
  • ROW:基于行的复制,日志中会记录成每一行数据被修改的形式,然后在slave端再对相同的数据进行修改记录下每一行数据修改的细节,可以解决函数、存储过程等在slave机器的复制问题,但这种方式日志量较大,性能不如Statement。举个例子,假设update语句更新10行数据,Statement方式就记录这条update语句,Row方式会记录被修改的10行数据。
  • MIXED:混合模式复制,实际就是前两种模式的结合,在Mixed模式下,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种,如果sql里有函数或一些在执行时才知道结果的情况,会选择Row,其它情况选择Statement,推荐使用这一种。

binlog写入磁盘机制

binlog写入磁盘机制主要通过 sync_binlog 参数控制,默认值是 0。

  • 为0的时候,表示每次提交事务都只 write 到page cache,由系统自行判断什么时候执行 fsync 写入磁盘。虽然性能得到提升,但是机器宕机,page cache里面的 binlog 会丢失。
  • 也可以设置为1,表示每次提交事务都会执行 fsync 写入磁盘,这种方式最安全。
  • 还有一种折中方式,可以设置为N(N>1),表示每次提交事务都write 到page cache,但累积N个事务后才 fsync 写入磁盘,这种如果机器宕机会丢失N个事务的binlog。

 

发生以下任何事件时, binlog日志文件会重新生成:

  • 服务器启动或重新启动
  • 服务器刷新日志,执行命令flush logs
  • 日志文件大小达到 max_binlog_size 值,默认值为 1GB

删除 binlog 日志文件

删除当前的binlog文件
reset master;
# 删除指定日志文件之前的所有日志文件,下面这个是删除6之前的所有日志文件,当前这个文件不删除
purge master logs to 'mysql-binlog.000010';
# 删除指定日期前的日志索引中binlog日志文件
purge master logs before '2024-09-21 14:00:00';

查看 binlog 日志文件

可以用mysql自带的命令工具 mysqlbinlog 查看binlog日志内容

# 查看bin-log二进制文件(命令行方式,不用登录mysql)
mysqlbinlog --no-defaults -v --base64-output=decode-rows D:/dev/mysql-5.7.25-winx64/data/mysql-binlog.000007 # 查看bin-log二进制文件(带查询条件)
#根据时间日期
mysqlbinlog --no-defaults -v --base64-output=decode-rows D:/dev/mysql-5.7.25-winx64/data/mysql-binlog.000007 start-datetime="2023-09-03 00:00:00" stop-datetime="2023-09-31 00:00:00"
#根据位置
mysqlbinlog --no-defaults -v --base64-output=decode-rows D:/dev/mysql-5.7.25-winx64/data/mysql-binlog.000007 start-position="5000" stop-position="20000"mysqlbinlog常见的选项有以下几个:
--start-datetime:从二进制日志中读取指定等于时间戳或者晚于本地计算机的时间
--stop-datetime:从二进制日志中读取指定小于时间戳或者等于本地计算机的时间 取值和上述一样
--start-position:从二进制日志中读取指定position 事件位置作为开始。
--stop-position:从二进制日志中读取指定position 事件位置作为事件截至

查询结果如下

/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#230823 23:40:58 server id 1  end_log_pos 123 CRC32 0xed27440b  Start: binlog v 4, server v 5.7.43-log created 230823 23:40:58 at startup
ROLLBACK/*!*/;
# at 123
#230823 23:40:58 server id 1  end_log_pos 154 CRC32 0x57d3c47c  Previous-GTIDs
# [empty]
# at 154
#230903 21:45:18 server id 1  end_log_pos 219 CRC32 0xba0e6d16  Anonymous_GTID  last_committed=0        sequence_number=1       rbr_only=no
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 219
#230903 21:45:18 server id 1  end_log_pos 404 CRC32 0xdb84c89b  Query   thread_id=2     exec_time=0     error_code=0
use `test1`/*!*/;
SET TIMESTAMP=1693748718/*!*/;
SET @@session.pseudo_thread_id=2/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1436549152/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb4 *//*!*/;
SET @@session.character_set_client=45,@@session.collation_connection=45,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
ALTER TABLE `test1`.`train_user`
DROP INDEX `idx_name`,
DROP INDEX `idx_telephone`,
DROP INDEX `idx_mail`
/*!*/;
# at 404
#230903 21:48:27 server id 1  end_log_pos 469 CRC32 0x95afb5c7  Anonymous_GTID  last_committed=1        sequence_number=2       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 469
#230903 21:48:02 server id 1  end_log_pos 542 CRC32 0x361725c8  Query   thread_id=2     exec_time=0     error_code=0
SET TIMESTAMP=1693748882/*!*/;
BEGIN
/*!*/;
# at 542
#230903 21:48:02 server id 1  end_log_pos 609 CRC32 0x2d1b1977  Table_map: `test1`.`train_user` mapped to number 121
# at 609
#230903 21:48:02 server id 1  end_log_pos 801 CRC32 0x280ab5da  Update_rows: table id 121 flags: STMT_END_F
### UPDATE `test1`.`train_user`
### WHERE
###   @1=1
###   @2='test'
###   @3='25D55AD283AA400AF464C76D713C07AD'
###   @4='123456789'
###   @5='test@test.com'
###   @6=1
### SET
###   @1=1
###   @2='test'
###   @3='25D55AD283AA400AF464C76D713C07AD'
###   @4='13202013849'
###   @5='test@test.com'
###   @6=1
# at 801
#230903 21:48:27 server id 1  end_log_pos 832 CRC32 0x8fd4a4df  Xid = 156
COMMIT/*!*/;
# at 832
#230903 21:48:42 server id 1  end_log_pos 897 CRC32 0x995be1d1  Anonymous_GTID  last_committed=2        sequence_number=3       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 897
#230903 21:48:10 server id 1  end_log_pos 970 CRC32 0x0dda090a  Query   thread_id=3     exec_time=17    error_code=0
SET TIMESTAMP=1693748890/*!*/;
BEGIN
/*!*/;
# at 970
#230903 21:48:10 server id 1  end_log_pos 1037 CRC32 0x3333b17b         Table_map: `test1`.`train_user` mapped to number 121
# at 1037
#230903 21:48:10 server id 1  end_log_pos 1231 CRC32 0xef64abb3         Update_rows: table id 121 flags: STMT_END_F
### UPDATE `test1`.`train_user`
### WHERE
###   @1=1
###   @2='test'
###   @3='25D55AD283AA400AF464C76D713C07AD'
###   @4='13202013849'
###   @5='test@test.com'
###   @6=1
### SET
###   @1=1
###   @2='test'
###   @3='25D55AD283AA400AF464C76D713C07AD'
###   @4='17666031514'
###   @5='test@test.com'
###   @6=1
# at 1231
#230903 21:48:42 server id 1  end_log_pos 1262 CRC32 0xc8db8a4d         Xid = 171
COMMIT/*!*/;
# at 1262
#230903 21:52:21 server id 1  end_log_pos 1327 CRC32 0xa92e5799         Anonymous_GTID  last_committed=3        sequence_number=4       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 1327
#230903 21:52:21 server id 1  end_log_pos 1400 CRC32 0x145371dd         Query   thread_id=4     exec_time=0     error_code=0
SET TIMESTAMP=1693749141/*!*/;
BEGIN
/*!*/;
# at 1400
#230903 21:52:21 server id 1  end_log_pos 1467 CRC32 0xfc342a84         Table_map: `test1`.`train_user` mapped to number 121
# at 1467
#230903 21:52:21 server id 1  end_log_pos 1545 CRC32 0x312e239c         Write_rows: table id 121 flags: STMT_END_F
### INSERT INTO `test1`.`train_user`
### SET
###   @1=2
###   @2='lisan'
###   @3='Aa123456'
###   @4='18814094148'
###   @5=''
###   @6=0
# at 1545
#230903 21:52:21 server id 1  end_log_pos 1576 CRC32 0x0302a530         Xid = 204
COMMIT/*!*/;
# at 1576
#230903 21:53:16 server id 1  end_log_pos 1641 CRC32 0xff5518fe         Anonymous_GTID  last_committed=4        sequence_number=5       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 1641
#230903 21:53:16 server id 1  end_log_pos 1714 CRC32 0xbe05b40c         Query   thread_id=4     exec_time=0     error_code=0
SET TIMESTAMP=1693749196/*!*/;
BEGIN
/*!*/;
# at 1714
#230903 21:53:16 server id 1  end_log_pos 1781 CRC32 0xc4a966ca         Table_map: `test1`.`train_user` mapped to number 121
# at 1781
#230903 21:53:16 server id 1  end_log_pos 1916 CRC32 0xceb8fa72         Update_rows: table id 121 flags: STMT_END_F
### UPDATE `test1`.`train_user`
### WHERE
###   @1=2
###   @2='lisan'
###   @3='Aa123456'
###   @4='18814094148'
###   @5=''
###   @6=0
### SET
###   @1=2
###   @2='lisan'
###   @3='Aa123456'
###   @4='18814094148'
###   @5='2222@test.com'
###   @6=0
# at 1916
#230903 21:53:16 server id 1  end_log_pos 1947 CRC32 0x75d7152d         Xid = 212
COMMIT/*!*/;
# at 1947
#230903 21:53:21 server id 1  end_log_pos 2012 CRC32 0xaaad4f1d         Anonymous_GTID  last_committed=5        sequence_number=6       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 2012
#230903 21:53:21 server id 1  end_log_pos 2085 CRC32 0xeefb9dd0         Query   thread_id=4     exec_time=0     error_code=0
SET TIMESTAMP=1693749201/*!*/;

binlog日志文件恢复数据

        根据自己需要恢复数据的起始位置,进行定位,来恢复数据。每条sql的上下都有BEGIN和COMMIT, 我们可以根据位置来定位,也可以根据时间日期来定位。

        看上面的 binlog 日志,我们先根据位置来定位,找到需要恢复数据的BEGIN, 可以看到BEGIN前 的 at 1641 的起始位置,和COMMIT 后的 at 1947 的结束位置。

        此时我们可以根据mysqlbinlog 命令的起始位置来恢复数据。如下:

mysqlbinlog  --no-defaults --start-position=1641 --stop-position=1947 --database=test C:/ProgramData/MySQL/data/mysqlbinlog.000007 | mysql -uroot -padmin -v gorgor_user

        我们也可以根据时间日期来定位,进行数据的恢复。我们找到第一条sql BEGIN前面的时间戳标记 SET TIMESTAMP=1693749196,再找到第二条sql COMMIT后面的时间戳标记 SET TIMESTAMP=1693749201,转成datetime格式。

mysqlbinlog  --no-defaults --start-datetime="2023-9-3 21:53:16" --stop-datetime="2023-9-3 21:53:21" --database=test C:/ProgramData/MySQL/data/mysqlbinlog.000007 | mysql -uroot -padmin -v gorgor_user

 

 

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

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

相关文章

解决RabbitMQ设置x-max-length队列最大长度后不进入死信队列

解决RabbitMQ设置x-max-length队列最大长度后不进入死信队列 问题发现问题解决方法一&#xff1a;只监听死信队列&#xff0c;在死信队列里面处理业务逻辑方法二&#xff1a;修改预取值 问题发现 最近再学习RabbitMQ过程中&#xff0c;看到关于死信队列内容&#xff1a; 来自队…

Docker 容器技术:颠覆传统,重塑软件世界的新势力

一、Docker简介 什么是docker Docker 是一种开源的容器化平台&#xff0c;它可以让开发者将应用程序及其所有的依赖项打包成一个标准化的容器&#xff0c;从而实现快速部署、可移植性和一致性。 从功能角度来看&#xff0c;Docker 主要有以下几个重要特点&#xff1a; 轻量…

[Redis][数据类型]详细讲解

1.Redis 特殊数据结构 1.Streams 应用场景&#xff1a;主要用为队列(阻塞队列) 2.Geospatial 应用场景&#xff1a;用来存储坐标(经纬度) 3.HyperLogLog 应用场景&#xff1a;估算集合中的元素个数注意&#xff1a; HyperLogLog不存储元素的内容&#xff0c;但是能够记录“…

计算机毕设设计推荐-基于python+Djanog大数据的电影数据可视化分析

精彩专栏推荐订阅&#xff1a;在下方主页&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f496;&#x1f525;作者主页&#xff1a;计算机毕设木哥&#x1f525; &#x1f496; 文章目录 一、电影数据可视…

JavaWeb--纯小白笔记04:Tomcat整合IDEA

IDEA整合Tomcat 1.点击Idea的导航栏里的Run&#xff0c;选择Edit Configurations 2.点击左上角的""&#xff0c;向下翻找到Tomcat Server 选择里面的Local 3.创建一个web工程&#xff0c;点击IDEA的File-->new-->project 然后选择Java Enterprise&#xff0c;…

crosscrossover24支持的游戏有那些

CrossOver刚刚更新了24版本&#xff0c;支持《地平线零之曙光》、《以撒的结合&#xff1a;重生》等游戏。一起来看看它有哪些更新吧&#xff01;之前买过23版的用户可以在1年之内免费升级哦&#xff0c;点击这里查看升级教程。 一、功能优化 - 更新 Wine 至最新的稳定版 Wine …

七彩云南文化旅游网站设计与实现

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装七彩云南文化旅游网站软件来发挥其高效地信息处理的作用&am…

[机器学习]04-逻辑回归(python)-03-API与癌症分类案例讲解

逻辑回归&#xff08;Logistic Regression&#xff09; 的一API 介绍 关于如何配置模型中的优化器、正则化和惩罚项。 1. 逻辑回归 API 在 Scikit-learn 中&#xff0c;逻辑回归可以通过如下方式定义&#xff1a; from sklearn.linear_model import LogisticRegression ​ …

Web 安全(Web Security)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

Renesas R7FA8D1BH (Cortex®-M85)的 General PWM的应用实践

目录 概述 1 General PWM介绍 1.1 特性 1.2 定时器选择注意点 2 时钟配置 3 应用案例 3.1 基本定时器应用 3.2 定时器回调函数案例 3.3 输入捕捉功能案例 3.4 更新周期案例 3.5 更新占空比案例 3.6 单次触发脉冲案例 4 测试 4.1 代码介绍 4.2 验证 概述 本文主…

算法练习题25——leetcode3279统计重新排列后包含另一个字符串的子字符串的数目(滑动窗口 双指针 哈希)

题目描述 解题思路 本题用到了滑动窗口 双指针 哈希 刚开始我是没读懂题的因为我笨 我想把我的思路说一下 左端不轻易缩小 只有找到跟word2匹配了 比如说abbcdd 遍历到c的时候才能匹配这个word2 对吧 那么之后加上以一个d或者俩d 都符合了 然后我们算完了 才能缩小左端 扩大…

python爬虫案例——异步加载网站数据抓取,post请求(6)

文章目录 前言1、任务目标2、抓取流程2.1 分析网页2.2 编写代码2.3 思路分析前言 本篇案例主要讲解异步加载网站如何分析网页接口,以及如何观察post请求URL的参数,网站数据并不难抓取,主要是将要抓取的数据接口分析清楚,才能根据需求编写想要的代码。 1、任务目标 目标网…

STM32篇:按键点亮LED灯

输入&#xff08;按键&#xff09;&#xff1a;KEY1---PA0 KEY2---PA1 输出&#xff08;LED灯&#xff09;&#xff1a;LED1---PB8 LED2---PB9

【M-LOAM学习】

M-LOAM(INITIALIZATION) Article Analysis Scan-Based Motion Estimation 通过在consecutive frame (each LiDAR)&#xff08;因为omp parallel&#xff09;中寻找correspondences然后通过最小化所有考虑feature之间residual error的transformation between frame to frame 针…

(done) 声音信号处理基础知识(7) (Understanding Time Domain Audio Features)

参考&#xff1a;https://www.youtube.com/watch?vSRrQ_v-OOSg&t1s 时域特征包括&#xff1a; 1.幅度包络 2.均方根能量 3.过零率 振幅包络的定义&#xff1a;一个 frame 里&#xff0c;所有采样点中最大的振幅值 一个形象的关于振幅包络的可视化解释如下&#xff1a;…

MateBook 16s 2023在Deepin下开启性能模式,调节风扇转速到最大,全网首发!

方法 在Deepin下按住Fnp快捷键&#xff0c;开启性能模式。 验证 首先去debian下载acpi-call-dkms https://packages.debian.org/sid/all/acpi-call-dkms/download 然后使用root用户执行&#xff1a; apt install --simulate ./acpi-call-dkms_1.2.2-2.1_all.deb apt inst…

C++入门——(类的默认成员函数)析构函数

文章目录 一、析构函数二、析构函数的特点总结 一、析构函数 析构函数与构造函数功能相反&#xff0c;析构函数不是完成对对象本⾝的销毁&#xff0c;⽐如局部对象是存在栈帧的&#xff0c;函数结束栈帧销毁&#xff0c;他就释放了&#xff0c;不需要我们管&#xff0c;C规定对…

【ChatGPT】提示词助力广告文案、PPT制作与书籍推荐的高效新模式

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;高效广告推销文案提示词使用方法 &#x1f4af;AI自动生成PPT全流程提示词使用方法 &#x1f4af;精选书籍推荐爆款文案提示词使用方法 &#x1f4af;小结 &#x1f4af;…

第一个NDK项目

新建项目 选择Native C的项目&#xff0c;我这里给项目的命名是NDKTest。 目录分析 新增了一个cpp目录&#xff0c;里面有一个CMakeLists和.cpp文件。 CMakeLists 文件是用来配置C编译过程的。 # Sets the minimum CMake version required for this project. cmake_minimum_…

【解密 Kotlin 扩展函数】命名参数和默认值(十三)

导读大纲 1.0.1 命名参数1.0.2 默认参数值 上一节讲述如何自定义 joinToString 函数来代替集合的默认字符串表示 文末遗留下几个待优化问题–传送门 1.0.1 命名参数 我们要解决的第一个问题涉及函数调用的可读性 例如,请看下面的joinToString调用: joinToString(collection,&…