3.00001 postgres如何初始化系統參數?

文章目錄

    • 加載參數整體流程
    • 參數結構
      • 舉例:ConfigureNamesBool
    • 初始化參數 InitializeGUCOptions
      • build_guc_variables
      • InitializeOneGUCOption
      • InitializeGUCOptionsFromEnvironment
    • 命令行添加
    • SelectConfigFiles配置

加載參數整體流程

我們先看下guc參數是如何管理的。
在這里插入圖片描述
首先初始化GUC選項,將其設置為默認值;然后讀取命令行配置,最后讀取配置文件postgresql.conf中的配置項。

參數結構

有5類參數:ConfigureNamesBool、ConfigureNamesInt、ConfigureNamesReal、ConfigureNamesReal、ConfigureNamesEnum。

在guc_tables中定義了不同類型的參數清單:

struct config_bool ConfigureNamesBool[] (guc_tables.c:771)
struct config_int ConfigureNamesInt[]   (guc_tables.c:2056)
struct config_real ConfigureNamesReal[] (guc_tables.c:3678)
struct config_string ConfigureNamesString[] (guc_tables.c:3959)
struct config_enum ConfigureNamesEnum[]  (guc_tables.c:4736)

不同的參數類型結構體定義在guc_tables.h

struct config_generic (guc_tables.h:153) //被用于下面幾種類型參數的成員。
struct config_bool (guc_tables.h:198)
struct config_int (guc_tables.h:212)
struct config_real (guc_tables.h:228)
struct config_string  (guc_tables.h:254)
struct config_enum (guc_tables.h:268)

在guc_tables.h中定義了參數類型如下:guc_tables.h:21

enum config_type
{PGC_BOOL,PGC_INT,PGC_REAL,PGC_STRING,PGC_ENUM,
};

在guc_tables.c中定義了參數類型對應的值如下:guc_tables.c:731

const char *const config_type_names[] =
{[PGC_BOOL] = "bool",[PGC_INT] = "integer",[PGC_REAL] = "real",[PGC_STRING] = "string",[PGC_ENUM] = "enum",
};

舉例:ConfigureNamesBool

ConfigureNamesBool參數組,每一個成員都是一個結構體config_bool

struct config_bool ConfigureNamesBool[] =
{{{"backtrace_on_internal_error", PGC_SUSET, DEVELOPER_OPTIONS,gettext_noop("Log backtrace for any error with error code XX000 (internal error)."),NULL,GUC_NOT_IN_SAMPLE},&backtrace_on_internal_error,false,NULL, NULL, NULL},

結構體config_bool的定義如下:

struct config_bool
{struct config_generic gen;  //包含的config_generic結構體/* constant fields, must be set correctly in initial value: */bool	   *variable;bool		boot_val;GucBoolCheckHook check_hook;GucBoolAssignHook assign_hook;GucShowHook show_hook;/* variable fields, initialized at runtime: */bool		reset_val;void	   *reset_extra;
};

結構體config_generic的定義如下:

struct config_generic
{/* constant fields, must be set correctly in initial value: */const char *name;			/* name of variable - MUST BE FIRST */GucContext	context;		/* context required to set the variable */enum config_group group;	/* to help organize variables by function */const char *short_desc;		/* short desc. of this variable's purpose */const char *long_desc;		/* long desc. of this variable's purpose */int			flags;			/* flag bits, see guc.h *//* variable fields, initialized at runtime: */enum config_type vartype;	/* type of variable (set only at startup) */int			status;			/* status bits, see below */GucSource	source;			/* source of the current actual value */GucSource	reset_source;	/* source of the reset_value */GucContext	scontext;		/* context that set the current value */GucContext	reset_scontext; /* context that set the reset value */Oid			srole;			/* role that set the current value */Oid			reset_srole;	/* role that set the reset value */GucStack   *stack;			/* stacked prior values */void	   *extra;			/* "extra" pointer for current actual value */dlist_node	nondef_link;	/* list link for variables that have source* different from PGC_S_DEFAULT */slist_node	stack_link;		/* list link for variables that have non-NULL* stack */slist_node	report_link;	/* list link for variables that have the* GUC_NEEDS_REPORT bit set in status */char	   *last_reported;	/* if variable is GUC_REPORT, value last sent* to client (NULL if not yet sent) */char	   *sourcefile;		/* file current setting is from (NULL if not* set in config file) */int			sourceline;		/* line in source file */
};

初始化參數 InitializeGUCOptions

InitializeGUCOptionsbuild_guc_variables();InitializeOneGUCOption(guc_variables[i]);InitializeGUCOptionsFromEnvironment

build_guc_variables

完成空間申請與初始化,

  1. 會通過設定的參數組ConfigureNamesxxx中的vartype值;
  2. 將所有的參數保存在guc_hashtab全局hash桶內
  • 初始化所有的參數組的vartype為對應的config_type,
		struct config_bool *conf = &ConfigureNamesBool[i];/* Rather than requiring vartype to be filled in by hand, do this: */conf->gen.vartype = PGC_BOOL;num_vars++;
  • 創建hash結構
// (guc.c:976)
guc_hashtab = hash_create("GUC hash table",size_vars,&hash_ctl,HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);

其中的guc_hashtab為static的hash結構(guc.c:241):

static HTAB *guc_hashtab;		/* entries are GUCHashEntrys */...// HTAB定義如下:
/** Top control structure for a hashtable --- in a shared table, each backend* has its own copy (OK since no fields change at runtime)*/
struct HTAB
{HASHHDR    *hctl;			/* => shared control information */HASHSEGMENT *dir;			/* directory of segment starts */HashValueFunc hash;			/* hash function */HashCompareFunc match;		/* key comparison function */HashCopyFunc keycopy;		/* key copying function */HashAllocFunc alloc;		/* memory allocator */MemoryContext hcxt;			/* memory context if default allocator used */char	   *tabname;		/* table name (for error messages) */bool		isshared;		/* true if table is in shared memory */bool		isfixed;		/* if true, don't enlarge *//* freezing a shared table isn't allowed, so we can keep state here */bool		frozen;			/* true = no more inserts allowed *//* We keep local copies of these fixed values to reduce contention */Size		keysize;		/* hash key length in bytes */long		ssize;			/* segment size --- must be power of 2 */int			sshift;			/* segment shift = log2(ssize) */
};
  • 將參數加入guc_hashtable
		struct config_generic *gucvar = &ConfigureNamesBool[i].gen;//這一步會從guc_hashtab(靜態結構的hash表),中查找參數名(gucvar->name),沒有的話就會新建一個返回給hentryhentry = (GUCHashEntry *) hash_search(guc_hashtab,&gucvar->name,HASH_ENTER,&found);Assert(!found);//初始化添加時一定找不到參數名的,那么就會新建一個桶,同時把桶賦值gucvar即 &ConfigureNamesBool[i].gen;hentry->gucvar = gucvar;

其中,
結構體GUCHashEntry的定義鏈如下:

typedef struct
{const char *gucname;		/* hash key */struct config_generic *gucvar;	/* -> GUC's defining structure */
} GUCHashEntry;

hash_search(dynahash.c:955)函數定義如下,其直接套用下層hash_search_with_hash_value函數

void *
hash_search(HTAB *hashp,const void *keyPtr,HASHACTION action,bool *foundPtr)
{return hash_search_with_hash_value(hashp,keyPtr,hashp->hash(keyPtr, hashp->keysize),action,foundPtr);
}

hash_search_with_hash_value(dynahash.c:968)函數大致作用是:
在Bucket中一個個找,用currBucket判斷是否為null來確認是非存在對應的桶

// 在Bucket中一個個找,用currBucket判斷是否為null來確認是非存在對應的桶while (currBucket != NULL){if (currBucket->hashvalue == hashvalue &&match(ELEMENTKEY(currBucket), keyPtr, keysize) == 0)break;prevBucketPtr = &(currBucket->link);currBucket = *prevBucketPtr;
#ifdef HASH_STATISTICShash_collisions++;hctl->collisions++;
#endif}

針對不同的hashaction有不同的動作

// hashaction的定義如下(hsearch.h:110)
/* hash_search operations */
typedef enum
{HASH_FIND,HASH_ENTER,HASH_REMOVE,HASH_ENTER_NULL,
} HASHACTION;* action is one of:*		HASH_FIND: look up key in table*		HASH_ENTER: look up key in table, creating entry if not present*		HASH_ENTER_NULL: same, but return NULL if out of memory*		HASH_REMOVE: look up key in table, remove entry if present... ...
// (dynahash.c:1037)switch (action){case HASH_FIND:... case HASH_ENTER:case HASH_ENTER_NULL:/* Return existing element if found, else create one */if (currBucket != NULL)return (void *) ELEMENTKEY(currBucket);/* disallow inserts if frozen */if (hashp->frozen)elog(ERROR, "cannot insert into frozen hashtable \"%s\"",hashp->tabname);//重新申請一個hash bucketcurrBucket = get_hash_entry(hashp, freelist_idx);if (currBucket == NULL){/* out of memory */if (action == HASH_ENTER_NULL)return NULL;/* report a generic message */if (hashp->isshared)ereport(ERROR,(errcode(ERRCODE_OUT_OF_MEMORY),errmsg("out of shared memory")));elseereport(ERROR,(errcode(ERRCODE_OUT_OF_MEMORY),errmsg("out of memory")));}/* link into hashbucket chain */*prevBucketPtr = currBucket;currBucket->link = NULL;/* copy key into record */currBucket->hashvalue = hashvalue;hashp->keycopy(ELEMENTKEY(currBucket), keyPtr, keysize);/** Caller is expected to fill the data field on return.  DO NOT* insert any code that could possibly throw error here, as doing* so would leave the table entry incomplete and hence corrupt the* caller's data structure.*/return (void *) ELEMENTKEY(currBucket);}

在初始化參數是的堆棧如下:其中action是“HASH_ENTER”。

#0  hash_search_with_hash_value (hashp=0x1023f80, keyPtr=0xfb4c60 <ConfigureNamesBool>, hashvalue=1010527281, action=HASH_ENTER, foundPtr=0x7fffffffe05f) at dynahash.c:975
#1  0x0000000000bc1901 in hash_search (hashp=0x1023f80, keyPtr=0xfb4c60 <ConfigureNamesBool>, action=HASH_ENTER, foundPtr=0x7fffffffe05f) at dynahash.c:960
#2  0x0000000000bcd413 in build_guc_variables () at guc.c:985
#3  0x0000000000bce451 in InitializeGUCOptions () at guc.c:1546
#4  0x0000000000911a54 in PostmasterMain (argc=1, argv=0x1000ef0) at postmaster.c:585
#5  0x00000000007d3f97 in main (argc=1, argv=0x1000ef0) at main.c:197

如上所示,會使用get_hash_entry(dynahash.c:1256)重新創建一個bucket存儲某一個參數。存儲類型為GUCHashEntry。

InitializeOneGUCOption

代碼棧如下:

Breakpoint 1, InitializeOneGUCOption (gconf=0xfc39c8 <ConfigureNamesString+3400>) at guc.c:1648
1648            gconf->status = 0;
(gdb) bt
#0  InitializeOneGUCOption (gconf=0xfc39c8 <ConfigureNamesString+3400>) at guc.c:1648
#1  0x0000000000bce4a4 in InitializeGUCOptions () at guc.c:1558
#2  0x0000000000911a54 in PostmasterMain (argc=3, argv=0x1000ef0) at postmaster.c:585
#3  0x00000000007d3f97 in main (argc=3, argv=0x1000ef0) at main.c:197

其中
InitializeOneGUCOption函數的入參gconf來源如下,為GUCHashEntry->config_generic:

	hash_seq_init(&status, guc_hashtab);while ((hentry = (GUCHashEntry *) hash_seq_search(&status)) != NULL){/* Check mapping between initial and default value */Assert(check_GUC_init(hentry->gucvar));InitializeOneGUCOption(hentry->gucvar);}

即此時通過全局靜態變量guc_hashtab來一個個配置參數。配置過程調用InitializeOneGUCOption函數,具體步驟如下:

  • 第一步:填充統一的默認值:
	gconf->status = 0;gconf->source = PGC_S_DEFAULT;gconf->reset_source = PGC_S_DEFAULT;gconf->scontext = PGC_INTERNAL;gconf->reset_scontext = PGC_INTERNAL;gconf->srole = BOOTSTRAP_SUPERUSERID;gconf->reset_srole = BOOTSTRAP_SUPERUSERID;gconf->stack = NULL;gconf->extra = NULL;gconf->last_reported = NULL;gconf->sourcefile = NULL;gconf->sourceline = 0;
  • 第二部,初始化參數值
switch (gconf->vartype){case PGC_BOOL:{struct config_bool *conf = (struct config_bool *) gconf;bool		newval = conf->boot_val;void	   *extra = NULL;if (!call_bool_check_hook(conf, &newval, &extra,PGC_S_DEFAULT, LOG))elog(FATAL, "failed to initialize %s to %d",conf->gen.name, (int) newval);if (conf->assign_hook)conf->assign_hook(newval, extra);*conf->variable = conf->reset_val = newval;conf->gen.extra = conf->reset_extra = extra;break;}case PGC_INT:{......

此時newval值的來源在哪里?
查看此時的conf變量,發現它的初始值中就conf->boot_val就是1!!

(gdb) p *conf
$15 = {gen = {name = 0xe2dc71 "extra_float_digits", context = PGC_USERSET, group = CLIENT_CONN_LOCALE, short_desc = 0xe2dc88 "Sets the number of digits displayed for floating-point values.", long_desc = 0xe2dcc8 "This affects real, double precision, and geometric data types. A zero or negative parameter value is added to the standard number of digits (FLT_DIG or DBL_DIG as appropriate). Any value greater than "..., flags = 0, vartype = PGC_INT, status = 0, source = PGC_S_DEFAULT, reset_source = PGC_S_DEFAULT, scontext = PGC_INTERNAL, reset_scontext = PGC_INTERNAL, srole = 10, reset_srole = 10, stack = 0x0, extra = 0x0, nondef_link = {prev = 0x0, next = 0x0}, stack_link = {next = 0x0}, report_link = {next = 0x0}, last_reported = 0x0, sourcefile = 0x0, sourceline = 0}, variable = 0xfb49d8 <extra_float_digits>, boot_val = 1, min = -15, max = 3, check_hook = 0x0, assign_hook = 0x0, show_hook = 0x0, reset_val = 0, reset_extra = 0x0}

然而此時的conf 來源與gconf,而gconf來源于靜態變量guc_hashtab。其中保存的是struct config_int ConfigureNamesInt[]的地址。
查看config_int ConfigureNamesInt[];發現:

	{{"extra_float_digits", PGC_USERSET, CLIENT_CONN_LOCALE,gettext_noop("Sets the number of digits displayed for floating-point values."),gettext_noop("This affects real, double precision, and geometric data types. ""A zero or negative parameter value is added to the standard ""number of digits (FLT_DIG or DBL_DIG as appropriate). ""Any value greater than zero selects precise output mode.")},&extra_float_digits,1, -15, 3,NULL, NULL, NULL},

已經默認配置了初始值。見上面的“1,-15,3”分別對應指針conf的“boot_val,min,max”;
同時觀察整個ConfigureNamesInt數組,發現初始值也有一些宏,如下

	{/* Can't be set in postgresql.conf */{"server_version_num", PGC_INTERNAL, PRESET_OPTIONS,gettext_noop("Shows the server version as an integer."),NULL,GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE},&server_version_num,PG_VERSION_NUM, PG_VERSION_NUM, PG_VERSION_NUM,NULL, NULL, NULL},

即通過靜態參數組中的boot_val屬性為每個參數賦值。

InitializeGUCOptionsFromEnvironment

堆棧如下:

Breakpoint 1, InitializeGUCOptionsFromEnvironment () at guc.c:1596
warning: Source file is more recent than executable.
1596            env = getenv("PGPORT");
(gdb) bt
#0  InitializeGUCOptionsFromEnvironment () at guc.c:1596
#1  0x0000000000bce512 in InitializeGUCOptions () at guc.c:1578
#2  0x0000000000911a54 in PostmasterMain (argc=3, argv=0x1000ef0) at postmaster.c:585
#3  0x00000000007d3f97 in main (argc=3, argv=0x1000ef0) at main.c:197

其中主要調用SetConfigOption(guc.c:4275)來配置PGPORT、PGDATESTYLE、PGCLIENTENCODING這些linuc的宏(環境變量),確認postgresql中的port、datestyle、client_encoding等參數配置,如下圖:

	env = getenv("PGPORT");if (env != NULL)SetConfigOption("port", env, PGC_POSTMASTER, PGC_S_ENV_VAR);env = getenv("PGDATESTYLE");if (env != NULL)SetConfigOption("datestyle", env, PGC_POSTMASTER, PGC_S_ENV_VAR);env = getenv("PGCLIENTENCODING");if (env != NULL)SetConfigOption("client_encoding", env, PGC_POSTMASTER, PGC_S_ENV_VAR);

其中SetConfigOption(guc.c:4275)

void
SetConfigOption(const char *name, const char *value,GucContext context, GucSource source)
{(void) set_config_option(name, value, context, source,GUC_ACTION_SET, true, 0, false);
}

SetConfigOption嵌套set_config_option(guc.c:3333)函數如下:

int
set_config_option(const char *name, const char *value,GucContext context, GucSource source,GucAction action, bool changeVal, int elevel,bool is_reload)
{// bt如下
#0  set_config_with_handle (name=0xe2460e "transaction_isolation", handle=0x0, value=0xe245ff "read committed", context=PGC_POSTMASTER, source=PGC_S_OVERRIDE, srole=10, action=GUC_ACTION_SET, changeVal=true, elevel=0, is_reload=false) at guc.c:3401
#1  0x0000000000bd16fe in set_config_option (name=0xe2460e "transaction_isolation", value=0xe245ff "read committed", context=PGC_POSTMASTER, source=PGC_S_OVERRIDE, action=GUC_ACTION_SET, changeVal=true, elevel=0, is_reload=false) at guc.c:3351
#2  0x0000000000bd33a0 in SetConfigOption (name=0xe2460e "transaction_isolation", value=0xe245ff "read committed", context=PGC_POSTMASTER, source=PGC_S_OVERRIDE) at guc.c:4278
#3  0x0000000000bce4db in InitializeGUCOptions () at guc.c:1567
#4  0x0000000000911a54 in PostmasterMain (argc=3, argv=0x1000ef0) at postmaster.c:585
#5  0x00000000007d3f97 in main (argc=3, argv=0x1000ef0) at main.c:197

其也是通過將guc_hashtab全局hash表內的值拿出來,經過一系列對比之后進行賦值。

命令行添加

// postmaster.c:594while ((opt = getopt(argc, argv, "B:bC:c:D:d:EeFf:h:ijk:lN:OPp:r:S:sTt:W:-:")) != -1){switch (opt)case 'B':SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);break;... ...

這里面會對不同的參數做設置:
同時也是調用的SetConfigOption(guc.c:4275)完成重寫

SelectConfigFiles配置

調用堆棧如下:

(gdb) b SelectConfigFiles
Breakpoint 2 at 0xbcedd2: file guc.c, line 1795.
(gdb) r
Starting program: /home/db_postg/build/bin/postgres -D /home/db_postg/data
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".Breakpoint 2, SelectConfigFiles (userDoption=0x102bff0 "/home/db_postg/data", progname=0x10002a0 "postgres") at guc.c:1795
1795            if (userDoption)
(gdb) b read
Breakpoint 3 at 0x7ffff7d5bc10 (2 locations)
(gdb) b open
Breakpoint 4 at 0x7ffff7d5b920 (2 locations)
(gdb) c
Continuing.
Breakpoint 4, 0x00007ffff7d5b920 in open64 () from /lib64/libc.so.6
(gdb) bt
#0  0x00007ffff7d5b920 in open64 () from /lib64/libc.so.6
#1  0x00007ffff7ceb956 in _IO_file_open () from /lib64/libc.so.6
#2  0x00007ffff7cebb2a in __GI__IO_file_fopen () from /lib64/libc.so.6
#3  0x00007ffff7cdf41d in __fopen_internal () from /lib64/libc.so.6
#4  0x00000000009a72b3 in AllocateFile (name=0x102c130 "/home/db_postg/data/postgresql.conf", mode=0xe264d2 "r") at fd.c:2601
#5  0x0000000000bd947e in ParseConfigFile (config_file=0x10228b8 "/home/db_postg/data/postgresql.conf", strict=true, calling_file=0x0, calling_lineno=0, depth=0, elevel=15, head_p=0x7fffffffdfb8, tail_p=0x7fffffffdfb0)at guc-file.l:238
#6  0x0000000000bcc202 in ProcessConfigFileInternal (context=PGC_POSTMASTER, applySettings=true, elevel=15) at guc.c:299
#7  0x0000000000bd926d in ProcessConfigFile (context=PGC_POSTMASTER) at guc-file.l:152
#8  0x0000000000bcef97 in SelectConfigFiles (userDoption=0x102bff0 "/home/db_postg/data", progname=0x10002a0 "postgres") at guc.c:1864
#9  0x0000000000911f78 in PostmasterMain (argc=3, argv=0x1000ef0) at postmaster.c:768
#10 0x00000000007d3f97 in main (argc=3, argv=0x1000ef0) at main.c:197
(gdb) c
Continuing.Breakpoint 3, 0x00007ffff7d5bc10 in read () from /lib64/libc.so.6
(gdb) bt
#0  0x00007ffff7d5bc10 in read () from /lib64/libc.so.6
#1  0x00007ffff7ceb118 in __GI__IO_file_xsgetn () from /lib64/libc.so.6
#2  0x00007ffff7cdf983 in fread () from /lib64/libc.so.6
#3  0x0000000000bd8258 in yy_get_next_buffer () at guc-file.c:1369
#4  0x0000000000bd7d38 in GUC_yylex () at guc-file.c:1209
#5  0x0000000000bd9d22 in ParseConfigFp (fp=0x102e040, config_file=0x102c130 "/home/db_postg/data/postgresql.conf", depth=0, elevel=15, head_p=0x7fffffffdfb8, tail_p=0x7fffffffdfb0) at guc-file.l:388
#6  0x0000000000bd956e in ParseConfigFile (config_file=0x10228b8 "/home/db_postg/data/postgresql.conf", strict=true, calling_file=0x0, calling_lineno=0, depth=0, elevel=15, head_p=0x7fffffffdfb8, tail_p=0x7fffffffdfb0)at guc-file.l:262
#7  0x0000000000bcc202 in ProcessConfigFileInternal (context=PGC_POSTMASTER, applySettings=true, elevel=15) at guc.c:299
#8  0x0000000000bd926d in ProcessConfigFile (context=PGC_POSTMASTER) at guc-file.l:152
#9  0x0000000000bcef97 in SelectConfigFiles (userDoption=0x102bff0 "/home/db_postg/data", progname=0x10002a0 "postgres") at guc.c:1864
#10 0x0000000000911f78 in PostmasterMain (argc=3, argv=0x1000ef0) at postmaster.c:768
#11 0x00000000007d3f97 in main (argc=3, argv=0x1000ef0) at main.c:197

其中的主要動作有:
1、生成配置文件路徑并打開:

// SelectConfigFiles at guc.c:1826...if (userDoption)configdir = make_absolute_path(userDoption);elseconfigdir = make_absolute_path(getenv("PGDATA"));/*(gdb) p configdir$5 = 0x102c010 "/home/db_postg/data"*/... else if (configdir){fname = guc_malloc(FATAL,strlen(configdir) + strlen(CONFIG_FILENAME) + 2);sprintf(fname, "%s/%s", configdir, CONFIG_FILENAME);fname_is_malloced = false;}/*(gdb) p fname$4 = 0x1022868 "/home/db_postg/data/postgresql.conf"*/

2、配置數據目錄參數和配置文件參數

	SetConfigOption("config_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);... ...//第一次讀取配置文件,只是為了設置data目錄。ProcessConfigFile(PGC_POSTMASTER);...data_directory_rec = (struct config_string *)find_option("data_directory", false, false, PANIC);if (*data_directory_rec->variable)SetDataDir(*data_directory_rec->variable);else if (configdir)SetDataDir(configdir);... ...SetConfigOption("data_directory", DataDir, PGC_POSTMASTER, PGC_S_OVERRIDE);

3、配置其余參數

ProcessConfigFile(PGC_POSTMASTER);
...
SetConfigOption("hba_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
...
SetConfigOption("ident_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/17789.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/17789.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/17789.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

VUE3 學習筆記(6):data數據的監聽、表單綁定、操作DOM

data數據的監聽&#xff08;偵聽&#xff09; 對于data的值的監聽&#xff0c;可以用watch中與data中的參數命名一致的值做為函數進行獲取監聽變動前后的值再做邏輯判斷&#xff0c;如下圖所示。 示例代碼 <template><div><p :class"classDemo">{…

npm install 出錯,按照版本不匹配解決

一、現象 npm install npm WARN config global --global, --local are deprecated. Use --locationglobal instead. npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: panshi-main-web0.1.0 npm ERR! Found…

七大獲取免費https的方式

想要實現https訪問最簡單有效的的方法就是安裝SSL證書。只要證書正常安裝上以后&#xff0c;瀏覽器就不會出現網站不安全提示或者訪問被攔截的情況。下面我來教大家怎么去獲取免費的SSL證書&#xff0c;又如何安裝證書實現https訪問。 一、選擇免費SSL證書提供商 有多家機構提…

C#數據類型變量、常量

一個變量只不過是一個供程序操作的存儲區的名字。 在 C# 中&#xff0c;變量是用于存儲和表示數據的標識符&#xff0c;在聲明變量時&#xff0c;您需要指定變量的類型&#xff0c;并且可以選擇性地為其分配一個初始值。 在 C# 中&#xff0c;每個變量都有一個特定的類型&…

頭歌OpenGauss數據庫-I.復雜查詢第10關:換座位

任務描述 本關任務&#xff1a;改變相鄰倆學生的座位。 小美是一所中學的信息科技老師&#xff0c;她有一張 tb_Seat座位表&#xff0c;平時用來儲存學生名字和與他們相對應的座位 id。 tb_Seat表結構數據如下&#xff1a; idname1Elon2Donny3Carey4Karin5Larisa 現在小美想改變…

規則引擎 | 減少判斷嵌套

文章目錄 目前市面上具體的規則引擎產品有&#xff1a;droolsVisualRulesEasy RulesMandaraxIBM iLog其中使用最為廣泛并且開源的是drools

windows驅動開發-PCI討論(二)

認識PCI設備&#xff0c;還是要從配置空間說起&#xff0c;當PCI在ACPI和PCI復合體上電和枚舉完成后&#xff0c;PCI根復合體會從PCI設備讀出PCI設備的配置空間&#xff0c;許多信息(例如寄存器、內存空間、中斷信息等等)都是是從配置空間獲取的&#xff0c;所以接下來會詳細講…

動手學操作系統(三、通過IO接口直接控制顯卡)

動手學操作系統&#xff08;三、通過IO接口直接控制顯卡&#xff09; 在之前的學習內容中&#xff0c;我們成功編寫了MBR主引導記錄&#xff0c;在終端上進行了打印顯示&#xff0c;在這一節我們使用MBR通過IO接口來直接控制顯卡輸出字符。 文章目錄 動手學操作系統&#xff0…

PostgreSQL Windows 數據庫主從模式 熱同步

1.操作主服務器 1.1修改pg_hba.conf // 這邊就設置所有用戶&#xff0c;所有ip都可以交互 host replication all 0.0.0.0/0 md52.2 創建流復制用戶 // 創建流復制用戶replicator CREATE USER replica REPLICATION LOGIN PASSWORD replica…

邏輯回歸(頭歌)

第1關&#xff1a;邏輯回歸算法大體思想 #encodingutf8import numpy as np#sigmoid函數 def sigmoid(t):#輸入&#xff1a;負無窮到正無窮的實數#輸出&#xff1a;轉換后的概率值#********** Begin **********#result 1.0 / (1 np.exp(-t))#********** End **********#retur…

43、Flink 的 Window Join 詳解

1.Window Join a&#xff09;概述 Window join 作用在兩個流中有相同 key 且處于相同窗口的元素上&#xff0c;窗口可以通過 window assigner 定義&#xff0c;并且兩個流中的元素都會被用于計算窗口的結果。 兩個流中的元素在組合之后&#xff0c;會被傳遞給用戶定義的 Joi…

外匯天眼:野村證券和Laser Digital與GMO互聯網集團合作發行日元和美元穩定幣

野村控股和Laser Digital將與GMO互聯網集團合作&#xff0c;在日本探索發行日元和美元穩定幣。GMO互聯網集團的美國子公司GMO-Z.com Trust Company, Inc. 在紐約州金融服務部的監管框架下&#xff0c;在以太坊、恒星幣和Solana等主要區塊鏈上發行穩定幣。GMO-Z.com Trust Compa…

MySQL增刪查改進階

數據庫約束表的關系增刪查改 目錄 一.數據庫約束類型 NOT NULL約束類型 UNIQUE 唯一約束 DEFAULT 默認值約束 PRIMARY KEY&#xff1a;主鍵約束 FOREIGN KEY :W外鍵約束 二&#xff0c;查詢 count&#xff08;&#xff09;兩種用法 sum&#xff0c;avg&#xff0c;max…

Vue3_創建項目

目錄 一、創建vue項目 1.下載vue 2.進入剛才創建的項目 3.安裝依賴 4.運行項目 ?5.打包項目放入生產環境 二、vue項目組成 1.項目文件結構 2.項目重要文件 Vue (發音為 /vju?/&#xff0c;類似 view) 是一款用于構建用戶界面的 JavaScript 框架。它基于標準 HTML、C…

Go語言中實現RSA加解密、簽名驗證算法

隨著互聯網的高速發展&#xff0c;人們對安全的要求也越來越高。密碼學中兩大經典算法&#xff0c;一個是對稱加解密&#xff0c;另一個是非對稱加解密&#xff0c;這里就來分享一下非對稱加密算法的代表&#xff1a;RSA加解密。 在Go語言中實現RSA加解密還是比較簡單的&#…

【安全產品】基于HFish的MySQL蜜罐溯源實驗記錄

MySQL蜜罐對攻擊者機器任意文件讀取 用HFish在3306端口部署MySQL蜜罐 配置讀取文件路徑 攻擊者的mysql客戶端版本為5.7(要求低于8.0) 之后用命令行直連 mysql -h 124.222.136.33 -P 3306 -u root -p 可以看到成功連上蜜罐的3306服務&#xff0c;但進行查詢后會直接lost con…

ai機器人電銷資源有哪些?真的能幫到我們提高效率嗎ai智能語音機器人部署

隨著互聯網科技的發展&#xff0c;各種各樣的科技產物都應用于電銷企業&#xff0c;ai機器人電銷就是其中一個。那么ai機器人電銷可靠嗎&#xff1f;ai機器人電銷資源有哪些&#xff1f;我們一起來看看。 AI機器人在電銷資源方面有以下一些用途和功能&#xff1a; 自動識別潛在…

for循環綁定id,更新html頁面的文字內容

需求&#xff1a;將方法中內容對齊 實現方式 給for循環中每個方法添加一個動態的id在DOM結果渲染完后&#xff0c;更新頁面數據&#xff0c;否則會報錯&#xff0c;找不到對應節點或對應節點為空 <view v-for"(item, index) in itemList" :key"index"…

OWASP十大API漏洞解析:如何抵御Bot攻擊?

新型數字經濟中&#xff0c;API是物聯網設備、Web和移動應用以及業務合作伙伴流程的入口點。然而&#xff0c;API也是犯罪分子的前門&#xff0c;許多人依靠Bot來發動攻擊。對于安全團隊來說&#xff0c;保護API并緩解Bot攻擊至關重要。那么Bot在API攻擊中處于怎樣的地位&#…

香橙派Kunpeng Pro測評

目錄 香橙派Kunpeng Pro開發板試用體驗 觀察理解與適用場景 體驗步驟 試用感受