PostgreSQL的学习心得和知识总结(一百三十九)|深入理解PostgreSQL数据库GUC参数 allow_alter_system 的使用和原理


注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下:

1、参考书籍:《PostgreSQL数据库内核分析》
2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》
3、PostgreSQL数据库仓库链接,点击前往
4、日本著名PostgreSQL数据库专家 铃木启修 网站主页,点击前往
5、参考书籍:《PostgreSQL中文手册》
6、参考书籍:《PostgreSQL指南:内幕探索》,点击前往
7、参考书籍:《事务处理 概念与技术》
8、PgSQL · 性能优化 · PostgreSQL TPC-C极限优化玩法,点击前往


1、本文内容全部来源于开源社区 GitHub和以上博主的贡献,本文也免费开源(可能会存在问题,评论区等待大佬们的指正)
2、本文目的:开源共享 抛砖引玉 一起学习
3、本文不提供任何资源 不存在任何交易 与任何组织和机构无关
4、大家可以根据需要自行 复制粘贴以及作为其他个人用途,但是不允许转载 不允许商用 (写作不易,还请见谅 💖)
5、本文内容基于PostgreSQL master源码开发而成


深入理解PostgreSQL数据库GUC参数 allow_alter_system 的使用和原理

  • 文章快速说明索引
  • 参数使用背景说明
    • 背景
    • 使用
  • 参数实现源码解析



文章快速说明索引

学习目标:

做数据库内核开发久了就会有一种 少年得志,年少轻狂 的错觉,然鹅细细一品觉得自己其实不算特别优秀 远远没有达到自己想要的。也许光鲜的表面掩盖了空洞的内在,每每想到于此,皆有夜半临渊如履薄冰之感。为了睡上几个踏实觉,即日起 暂缓其他基于PostgreSQL数据库的兼容功能开发,近段时间 将着重于学习分享Postgres的基础知识和实践内幕。


学习内容:(详见目录)

1、深入理解PostgreSQL数据库GUC参数 allow_alter_system 的使用和原理


学习时间:

2024年04月21日 14:44:16


学习产出:

1、PostgreSQL数据库基础知识回顾 1个
2、CSDN 技术博客 1篇
3、PostgreSQL数据库内核深入学习


注:下面我们所有的学习环境是Centos8+PostgreSQL master +Oracle19C+MySQL8.0

postgres=# select version();
                                                  version                                                   
------------------------------------------------------------------------------------------------------------
 PostgreSQL 17devel on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-21), 64-bit
(1 row)

postgres=#

#-----------------------------------------------------------------------------#

SQL> select * from v$version;          

BANNER        Oracle Database 19c EE Extreme Perf Release 19.0.0.0.0 - Production	
BANNER_FULL	  Oracle Database 19c EE Extreme Perf Release 19.0.0.0.0 - Production Version 19.17.0.0.0	
BANNER_LEGACY Oracle Database 19c EE Extreme Perf Release 19.0.0.0.0 - Production	
CON_ID 0


#-----------------------------------------------------------------------------#

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.27    |
+-----------+
1 row in set (0.06 sec)

mysql>

参数使用背景说明

背景

2024/03/29日,PostgreSQL新增一个GUC参数,如下:

  • Discussion: Possibility to disable ALTER SYSTEM,点击前往

添加allow_alter_system GUC


这个被标记为PGC_SIGHUP,所以只能在配置文件中设置,不能在其他地方设置;并且它还被标记为GUC_DISALLOW_IN_AUTO_FILE,因此不能使用ALTER SYSTEM进行设置。当设置为 false 时,不允许使用 ALTER SYSTEM 命令


人们非常担心这会被误解为安全功能,但事实并非如此,因为坚定的超级用户可以通过多种方式绕过它。因此,我们在文档的措辞上做了很多工作,希望避免任何此类混乱


官方文档的解释,如下:

当allow_alter_system设置为off时,执行ALTER SYSTEM命令会返回错误。该参数只能在 postgresql.conf 文件或服务器命令行中设置。默认值是打开的

请注意,此设置不得视为安全功能。它仅禁用 ALTER SYSTEM 命令。它不会阻止超级用户使用其他 SQL 命令更改配置。超级用户有多种在操作系统级别执行 shell 命令的方法,因此可以修改 postgresql.auto.conf,无论此设置的值如何

关闭此设置适用于 PostgreSQL 配置由某些外部工具管理的环境。在这种环境中,善意的超级用户可能会错误地使用 ALTER SYSTEM 来更改配置,而不是使用外部工具。这可能会导致意外行为,例如外部工具在稍后更新配置时覆盖更改。将此参数设置为关闭可以帮助避免此类错误

该参数仅控制 ALTER SYSTEM 的使用。即使allow_alter_system设置为off,存储在postgresql.auto.conf中的设置也会生效


使用

接下来看一个简单的使用,示例1如下:

[postgres@localhost:~/test/bin]$ ./psql 
psql (17devel)
Type "help" for help.

postgres=# show timezone;
      TimeZone       
---------------------
 America/Los_Angeles
(1 row)

postgres=# set timezone = 'PRC';
SET
postgres=# show timezone;
 TimeZone 
----------
 PRC
(1 row)

postgres=# select now();
              now              
-------------------------------
 2024-04-18 15:35:49.411729+08
(1 row)

postgres=# reset timezone;
RESET
postgres=# show timezone;
      TimeZone       
---------------------
 America/Los_Angeles
(1 row)

postgres=# select now();
              now              
-------------------------------
 2024-04-18 00:36:06.505543-07
(1 row)

postgres=# alter system set timezone = 'PRC';
2024-04-18 00:36:23.026 PDT [30697] ERROR:  ALTER SYSTEM is not allowed in this environment
2024-04-18 00:36:23.026 PDT [30697] STATEMENT:  alter system set timezone = 'PRC';
ERROR:  ALTER SYSTEM is not allowed in this environment
postgres=# 
postgres=# show timezone;
      TimeZone       
---------------------
 America/Los_Angeles
(1 row)

postgres=# show allow_alter_system;
 allow_alter_system 
--------------------
 off
(1 row)

postgres=# alter system set allow_alter_system = on;
2024-04-18 00:40:03.694 PDT [30697] ERROR:  ALTER SYSTEM is not allowed in this environment
2024-04-18 00:40:03.694 PDT [30697] STATEMENT:  alter system set allow_alter_system = on;
ERROR:  ALTER SYSTEM is not allowed in this environment
postgres=#
[postgres@localhost:~/test/bin]$ cat test/postgresql.conf | grep allow_alter_system
allow_alter_system = off
[postgres@localhost:~/test/bin]$

示例2,如下:

[postgres@localhost:~/test/bin]$ cat test/postgresql.conf | grep allow_alter_system
allow_alter_system = off
[postgres@localhost:~/test/bin]$ 
[postgres@localhost:~/test/bin]$ vim test/postgresql.auto.conf 
[postgres@localhost:~/test/bin]$ 
[postgres@localhost:~/test/bin]$ cat test/postgresql.auto.conf 
# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
allow_alter_system = on
[postgres@localhost:~/test/bin]$ 
[postgres@localhost:~/test/bin]$ ./pg_ctl restart -D test/
waiting for server to shut down....2024-04-24 23:05:34.217 PDT [30683] LOG:  received fast shutdown request
2024-04-24 23:05:34.219 PDT [30683] LOG:  aborting any active transactions
2024-04-24 23:05:34.220 PDT [30683] LOG:  background worker "logical replication launcher" (PID 30689) exited with exit code 1
2024-04-24 23:05:34.221 PDT [30684] LOG:  shutting down
2024-04-24 23:05:34.240 PDT [30683] LOG:  database system is shut down
 done
server stopped
waiting for server to start....2024-04-24 23:05:34.361 PDT [50234] LOG:  starting PostgreSQL 17devel on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-21), 64-bit
2024-04-24 23:05:34.361 PDT [50234] LOG:  listening on IPv6 address "::1", port 5432
2024-04-24 23:05:34.361 PDT [50234] LOG:  listening on IPv4 address "127.0.0.1", port 5432
2024-04-24 23:05:34.363 PDT [50234] LOG:  listening on Unix socket "/tmp/.s.PGSQL.5432"
2024-04-24 23:05:34.366 PDT [50237] LOG:  database system was shut down at 2024-04-24 23:05:34 PDT
2024-04-24 23:05:34.370 PDT [50234] LOG:  database system is ready to accept connections
 done
server started
[postgres@localhost:~/test/bin]$ ./psql 
psql (17devel)
Type "help" for help.

postgres=# show allow_alter_system;
 allow_alter_system 
--------------------
 on
(1 row)

postgres=# show timezone;
      TimeZone       
---------------------
 America/Los_Angeles
(1 row)

postgres=# alter system set timezone = 'PRC';
ALTER SYSTEM
postgres=# alter system set allow_alter_system = off;
2024-04-24 23:06:26.063 PDT [50248] ERROR:  parameter "allow_alter_system" cannot be changed
2024-04-24 23:06:26.063 PDT [50248] STATEMENT:  alter system set allow_alter_system = off;
ERROR:  parameter "allow_alter_system" cannot be changed
postgres=#

参数实现源码解析

guc定义,如下:

// src\backend\utils\misc\guc_tables.c

	{
		/*
		 * This setting itself cannot be set by ALTER SYSTEM to avoid an
		 * operator turning this setting off by using ALTER SYSTEM, without a
		 * way to turn it back on.
		 *  
		 * 此设置本身无法通过 ALTER SYSTEM 设置,以避免操作员使用 ALTER SYSTEM 关闭此设置
		 * 而无法将其重新打开
		 */
		{"allow_alter_system", PGC_SIGHUP, COMPAT_OPTIONS_OTHER,
			gettext_noop("Allows running the ALTER SYSTEM command."),
			gettext_noop("Can be set to off for environments where global configuration "
						 "changes should be made using a different method."),
			GUC_DISALLOW_IN_AUTO_FILE
		},
		&AllowAlterSystem,
		true,
		NULL, NULL, NULL
	},

该参数真实使用的逻辑,如下:

// src\backend\utils\misc\guc.c

/*
 * Execute ALTER SYSTEM statement.
 *
 * Read the old PG_AUTOCONF_FILENAME file, merge in the new variable value,
 * and write out an updated file.  If the command is ALTER SYSTEM RESET ALL,
 * we can skip reading the old file and just write an empty file.
 * 读取旧的 PG_AUTOCONF_FILENAME 文件,合并新的变量值,并写出更新的文件
 * 如果命令是 ALTER SYSTEM RESET ALL,我们可以跳过读取旧文件,只写入一个空文件
 *
 * An LWLock is used to serialize updates of the configuration file.
 * LWLock 用于序列化配置文件的更新
 *
 * In case of an error, we leave the original automatic
 * configuration file (PG_AUTOCONF_FILENAME) intact.
 * 如果出现错误,我们会保留原始自动配置文件(PG_AUTOCONF_FILENAME)不变
 */
void
AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
{
	char	   *name;
	char	   *value;
	bool		resetall = false;
	ConfigVariable *head = NULL;
	ConfigVariable *tail = NULL;
	volatile int Tmpfd;
	char		AutoConfFileName[MAXPGPATH];
	char		AutoConfTmpFileName[MAXPGPATH];

	/*
	 * Extract statement arguments
	 */
	name = altersysstmt->setstmt->name;

	if (!AllowAlterSystem)
		ereport(ERROR,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("ALTER SYSTEM is not allowed in this environment")));

	switch (altersysstmt->setstmt->kind)
	{
		case VAR_SET_VALUE:
			value = ExtractSetVariableArgs(altersysstmt->setstmt);
			break;

		case VAR_SET_DEFAULT:
		case VAR_RESET:
			value = NULL;
			break;

		case VAR_RESET_ALL:
			value = NULL;
			resetall = true;
			break;

		default:
			elog(ERROR, "unrecognized alter system stmt type: %d",
				 altersysstmt->setstmt->kind);
			break;
	}

	/*
	 * Check permission to run ALTER SYSTEM on the target variable
	 */
	if (!superuser())
	{
		if (resetall)
			ereport(ERROR,
					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
					 errmsg("permission denied to perform ALTER SYSTEM RESET ALL")));
		else
		{
			AclResult	aclresult;

			aclresult = pg_parameter_aclcheck(name, GetUserId(),
											  ACL_ALTER_SYSTEM);
			if (aclresult != ACLCHECK_OK)
				ereport(ERROR,
						(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
						 errmsg("permission denied to set parameter \"%s\"",
								name)));
		}
	}

	/*
	 * Unless it's RESET_ALL, validate the target variable and value
	 */
	if (!resetall)
	{
		struct config_generic *record;

		/* We don't want to create a placeholder if there's not one already */
		record = find_option(name, false, true, DEBUG5);
		if (record != NULL)
		{
			/*
			 * Don't allow parameters that can't be set in configuration files
			 * to be set in PG_AUTOCONF_FILENAME file.
			 */
			if ((record->context == PGC_INTERNAL) ||
				(record->flags & GUC_DISALLOW_IN_FILE) ||
				(record->flags & GUC_DISALLOW_IN_AUTO_FILE))
				ereport(ERROR,
						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
						 errmsg("parameter \"%s\" cannot be changed",
								name)));

			/*
			 * If a value is specified, verify that it's sane.
			 */
			if (value)
			{
				union config_var_val newval;
				void	   *newextra = NULL;

				if (!parse_and_validate_value(record, name, value,
											  PGC_S_FILE, ERROR,
											  &newval, &newextra))
					ereport(ERROR,
							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
							 errmsg("invalid value for parameter \"%s\": \"%s\"",
									name, value)));

				if (record->vartype == PGC_STRING && newval.stringval != NULL)
					guc_free(newval.stringval);
				guc_free(newextra);
			}
		}
		else
		{
			/*
			 * Variable not known; check we'd be allowed to create it.  (We
			 * cannot validate the value, but that's fine.  A non-core GUC in
			 * the config file cannot cause postmaster start to fail, so we
			 * don't have to be too tense about possibly installing a bad
			 * value.)
			 */
			(void) assignable_custom_variable_name(name, false, ERROR);
		}

		/*
		 * We must also reject values containing newlines, because the grammar
		 * for config files doesn't support embedded newlines in string
		 * literals.
		 */
		if (value && strchr(value, '\n'))
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
					 errmsg("parameter value for ALTER SYSTEM must not contain a newline")));
	}

	/*
	 * PG_AUTOCONF_FILENAME and its corresponding temporary file are always in
	 * the data directory, so we can reference them by simple relative paths.
	 */
	snprintf(AutoConfFileName, sizeof(AutoConfFileName), "%s",
			 PG_AUTOCONF_FILENAME);
	snprintf(AutoConfTmpFileName, sizeof(AutoConfTmpFileName), "%s.%s",
			 AutoConfFileName,
			 "tmp");

	/*
	 * Only one backend is allowed to operate on PG_AUTOCONF_FILENAME at a
	 * time.  Use AutoFileLock to ensure that.  We must hold the lock while
	 * reading the old file contents.
	 */
	LWLockAcquire(AutoFileLock, LW_EXCLUSIVE);

	/*
	 * If we're going to reset everything, then no need to open or parse the
	 * old file.  We'll just write out an empty list.
	 */
	if (!resetall)
	{
		struct stat st;

		if (stat(AutoConfFileName, &st) == 0)
		{
			/* open old file PG_AUTOCONF_FILENAME */
			FILE	   *infile;

			infile = AllocateFile(AutoConfFileName, "r");
			if (infile == NULL)
				ereport(ERROR,
						(errcode_for_file_access(),
						 errmsg("could not open file \"%s\": %m",
								AutoConfFileName)));

			/* parse it */
			if (!ParseConfigFp(infile, AutoConfFileName, CONF_FILE_START_DEPTH,
							   LOG, &head, &tail))
				ereport(ERROR,
						(errcode(ERRCODE_CONFIG_FILE_ERROR),
						 errmsg("could not parse contents of file \"%s\"",
								AutoConfFileName)));

			FreeFile(infile);
		}

		/*
		 * Now, replace any existing entry with the new value, or add it if
		 * not present.
		 */
		replace_auto_config_value(&head, &tail, name, value);
	}

	/*
	 * Invoke the post-alter hook for setting this GUC variable.  GUCs
	 * typically do not have corresponding entries in pg_parameter_acl, so we
	 * call the hook using the name rather than a potentially-non-existent
	 * OID.  Nonetheless, we pass ParameterAclRelationId so that this call
	 * context can be distinguished from others.  (Note that "name" will be
	 * NULL in the RESET ALL case.)
	 *
	 * We do this here rather than at the end, because ALTER SYSTEM is not
	 * transactional.  If the hook aborts our transaction, it will be cleaner
	 * to do so before we touch any files.
	 */
	InvokeObjectPostAlterHookArgStr(ParameterAclRelationId, name,
									ACL_ALTER_SYSTEM,
									altersysstmt->setstmt->kind,
									false);

	/*
	 * To ensure crash safety, first write the new file data to a temp file,
	 * then atomically rename it into place.
	 *
	 * If there is a temp file left over due to a previous crash, it's okay to
	 * truncate and reuse it.
	 */
	Tmpfd = BasicOpenFile(AutoConfTmpFileName,
						  O_CREAT | O_RDWR | O_TRUNC);
	if (Tmpfd < 0)
		ereport(ERROR,
				(errcode_for_file_access(),
				 errmsg("could not open file \"%s\": %m",
						AutoConfTmpFileName)));

	/*
	 * Use a TRY block to clean up the file if we fail.  Since we need a TRY
	 * block anyway, OK to use BasicOpenFile rather than OpenTransientFile.
	 */
	PG_TRY();
	{
		/* Write and sync the new contents to the temporary file */
		write_auto_conf_file(Tmpfd, AutoConfTmpFileName, head);

		/* Close before renaming; may be required on some platforms */
		close(Tmpfd);
		Tmpfd = -1;

		/*
		 * As the rename is atomic operation, if any problem occurs after this
		 * at worst it can lose the parameters set by last ALTER SYSTEM
		 * command.
		 */
		durable_rename(AutoConfTmpFileName, AutoConfFileName, ERROR);
	}
	PG_CATCH();
	{
		/* Close file first, else unlink might fail on some platforms */
		if (Tmpfd >= 0)
			close(Tmpfd);

		/* Unlink, but ignore any error */
		(void) unlink(AutoConfTmpFileName);

		PG_RE_THROW();
	}
	PG_END_TRY();

	FreeConfigVariables(head);

	LWLockRelease(AutoFileLock);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【学习】​CSMM和CMMI的关系你了解吗

CMMI和CSMM都是评估和提升软件组织能力成熟度的模型&#xff0c;但它们在起源、应用范围、模型结构和实施目的等方面存在一些区别。在当今竞争激烈的软件市场中&#xff0c;提升软件能力成为了多数组织追求成功的关键因素。而选择适合的体系标准能够助力企业发展得更加迅速。作…

企业实施定制鞋厂ERP软件需要注意哪些问题?

企业实施定制鞋厂ERP软件是个复杂的管理系统工程&#xff0c;为了成功地为企业定制实施ERP软件&#xff0c;需要注意和解决几个关键的问题&#xff1a; . 确立ERP系统实施和定制的决策者&#xff1b;. 做好前期咨询与调研工作&#xff1b;. 做好系统产品或项目迭代规划&#x…

【MySQL 数据宝典】【内存结构】- 003 Change Buffer 详解

一、 Change Buffer基本概念 Change Buffer&#xff1a;写缓冲区,是针对二级索引(辅助索引) 页的更新优化措施。 作用: 在进行DML操作时&#xff0c;如果请求的是 辅助索引&#xff08;非唯一键索引&#xff09;没有在缓冲池 中时&#xff0c;并不会立刻将磁盘页加载到缓冲池…

【Qt】设置QT标准对话框为中文字体

设置QT标准对话框为中文字体 一、问题二、解决方法1、找到Qt内置的翻译文件 qt_zh_CN.qm2、在代码中加载该文件 一、问题 在Qt中我们使用的标准对话框都是英文&#xff0c;例如下面的 字体选择对话框&#xff0c;但是实际中我们需要构建的是中文对话框。 所以我们需要使用Qt官…

T1级,生产环境事故—Shell脚本一键备份K8s的YAML文件

大家好&#xff0c;我叫秋意零。 最近对公司进行日常运维工作时&#xff0c;出现了一个 T1 级别事故。导致公司的“酒云网”APP的无法使用。我和我领导一起搞了一个多小时&#xff0c;业务也停了一个多小时。 起因是&#xff1a;我的部门直系领导&#xff0c;叫我**删除一个 …

LeetCode 2739. 总行驶距离

题目链接https://leetcode.cn/problems/total-distance-traveled/?envTypedaily-question&envId2024-04-25 简单题&#xff0c;看代码思考一下即可理解 class Solution {public int distanceTraveled(int mainTank, int additionalTank) {int res 0;while (mainTank >…

OmniPlan Pro for Mac v4.8.0中文激活版 项目流程管理工具

OmniPlan Pro for Mac是一款功能强大的项目管理软件&#xff0c;它以其直观的用户界面和丰富的功能&#xff0c;帮助用户轻松管理各种复杂的项目。 OmniPlan Pro for Mac v4.8.0中文激活版 通过OmniPlan Pro&#xff0c;用户可以轻松创建任务&#xff0c;设置任务的开始和结束时…

苹果开发者 D-U-N-S 编号申请 经历 记录

首先查询需要注册的公司是否有D-U-N-S码 (如果之前该公司上架了苹果的app&#xff0c;那一定有的&#xff0c;直接查询就可以使用) 查询地址&#xff1a;Sign In - Apple 输入公司的相关信息后并没有找到。。 滑动到最下面之后&#xff0c;可以根据当前填写的内容进行提交申请…

iframe实现pdf预览,并使用pdf.js修改内嵌标题,解决乱码问题

项目中遇到文件预览功能,并且需要可以打印文件.下插件对于内网来说有点麻烦,正好iframe预览比较简单,且自带下载打印等功能按钮. 问题在于左上方的文件名乱码,网上找了一圈没有看到解决的,要么就是要收费要会员(ztmgs),要么直接说这东西改不了. 使用: 1.引入 PDF.js 库&…

Day51:动态规划 LeedCode 300.最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组

300. 最长递增子序列 中等 相关标签 相关企业 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] …

《动手学深度学习(Pytorch版)》Task02:预备知识——4.25打卡

《动手学深度学习&#xff08;Pytorch版&#xff09;》Task02&#xff1a;预备知识——4.25打卡 数据操作N维数组——张量创建数组访问元素入门初始化矩阵 运算符广播机制索引和切片节省内存转换为其他Python对象转换为NumPy张量ndarray张量转换为Python标量 数据预处理安装pan…

00后卷王拿下20k的测试岗,原来面试这么简单。。。

先说一下我的情况&#xff0c;某211本计算机&#xff0c;之前在深圳那边做少儿编程老师&#xff0c;之后内部平调回长沙这边&#xff0c;回来之后发现有点难&#xff0c;这边可能是业绩难做&#xff0c;虚假承诺很厉害&#xff0c;要给那些家长虚假承诺去骗人家&#xff0c;技术…

算法学习笔记Day8——回溯算法

本文解决几个问题&#xff1a; 回溯算法是什么&#xff1f;解决回溯算法相关的问题有什么技巧&#xff1f;回溯算法代码是否有规律可循&#xff1f; 一、介绍 1.回溯算法是什么&#xff1f; 回溯算法就是个多叉树的遍历问题&#xff0c;关键在于在前序和后序时间点做一些操作…

操作steam搬砖有哪些风险?你有中招吗?揭秘有没有规避技巧?

一、关于steam账号的地区问题&#xff1a; steam账号地区不要频繁的去更换&#xff0c;这样很容易导致让账号红信不能操作使用。 二、关于steam账号的充值问题&#xff1a; 一定要充值正规的礼品卡图&#xff0c;否则遇到黑卡分分钟让你的账号红锁&#xff0c;从而造成账号里…

Nginx下载安装,什么是nginx,什么是反向代理,Windows下、linux下安装nginx(保姆级教程)

文章目录 一、Nginx简介为什么要使用NginxNginx的特点Nginx的相关概念正向代理反向代理动静分离负载均衡 二、Nginx安装1. Windows安装2. Linux安装 一、Nginx简介 Nginx 是一个高性能的 HTTP&#xff08;静态资源服务器&#xff09; 和 反向代理 Web 服务器。 为什么要使用N…

MySQL锁详解

之前的博客给小伙伴们分享了java中的锁&#xff0c;今天我们一起来看看mysql中有什么锁吧 一、图示 二、粒度分类 2.1、全局锁&#xff1a; 什么是全局锁&#xff1f; MySQL的锁定主要分为全局锁、表锁和行锁。现在我们来看看MySQL全局锁。 MySQL全局锁是针对整个数据库的锁…

FreeRTOS之列表

1.FreeRTOS的列表和列表项十分重要。列表类相当于链表&#xff0c;列表项则相当于链表中的节点。列表项的地址是非连续的&#xff0c;列表项的数量可随时修改。在OS中的任务状态和数量会发生改变&#xff0c;因此使用列表可以很好的满足需求。 列表和列表项的相关定义与操作函…

网工交换基础——生成树协议(01)

一、生成树的技术概述 1、技术背景 二层交换机网络的冗余性导致出现二层环路&#xff1a; 人为因素导致的二层环路问题&#xff1a; 二层环路带来的网络问题&#xff1a; 生成树协议的概念&#xff1a; STP(Spanning Tree Protocol)是生成树协议的英文缩写。该协议可应用于在网…

vue3 -- 项目使用自定义字体font-family

在Vue 3项目中使用自定义字体(font-family)的方法与在普通的HTML/CSS项目中类似。可以按照以下步骤进行操作: 引入字体文件: 首先,确保你的字体文件(通常是.woff、.woff2、.ttf等格式)位于项目中的某个目录下,比如src/assets/font/。 在全局样式中定义字体: 在你的全局…

智慧健康旅居养老产业,做智慧旅居养老服务的公司

随着社会的进步和科技的飞速发展&#xff0c;传统的养老模式已经无法满足 现代老年人的多元化 需求。智慧健康旅居养老产业应运而生&#xff0c;成为了一种新型的养老模式&#xff0c;旨在为老年人提供更加舒适、便捷、安全的养老生活。随着社会的进步和人口老龄化趋势的加剧&a…