PostgreSql-学习05-逻辑解码

目录

一、环境

二、什么是逻辑解码

三、SQL接口控制逻辑解码

1、配置参数wal_level为logical

2、重启PG

3、验证参数wal_level

4、验证参数max_replication_slots

5、超级用户连接数据库

6、创建逻辑复制槽

7、查看逻辑复制槽

8、查看逻辑复制槽是否接收到数据变化

9、建表

10、查看逻辑复制槽是否接收到数据变化

11、查看逻辑复制槽是否接收到数据变化

12、插入多条数据

13、查看逻辑复制槽是否接收到数据变化

14、插入数据

15、逻辑复制槽预读数据变化

16、options参数改变格式

17、销毁逻辑复制槽

四、解码准备好的事务的SQL接口

1、设置参数max_prepared_transactions

2、重启PG

3、验证参数max_prepared_transactions

4、逻辑解码提交的准备事务

5、逻辑解码回滚的准备事务

五、逻辑解码插入多列多行

六、逻辑解码更新多行

七、逻辑解码删除多行

八、逻辑解码COPY

九、总结


一、环境

名称描述
PGPostgreSQL 16.3
CPUIntel(R) Core(TM) i5-1035G1 CPU @ 1.00GHz
OSCentOS Linux release 7.9.2009 (Core)

二、什么是逻辑解码

逻辑解码是一种将对数据库表的所有持久更改抽取到一种清晰、易于理解的格式的处理,这种技术允许在不了解数据库内部状态的详细知识的前提下解释该格式。

在PostgreSQL中,逻辑解码通过解码预写式日志的内容来实现,预写式日志描述了存储层面上的更改,而逻辑解码则会把更改解码成一种应用相关的形式,例如一个元组流或者 SQL 语句流。

三、SQL接口控制逻辑解码

1、配置参数wal_level为logical

[postgres@czg2 ~]$ cat /opt/Postgresql/PG_16_3/Data/postgresql.conf |grep wal_level
wal_level = logical                     # minimal, replica, or logical

2、重启PG

[root@czg2 ~]# service PG_16_3 restart
Restarting PostgreSQL: ok

3、验证参数wal_level

postgres=# \x
Expanded display is on.postgres=# SELECT * FROM PG_CATALOG.PG_SETTINGS WHERE NAME = 'wal_level';
-[ RECORD 1 ]---+--------------------------------------------------
name            | wal_level
setting         | logical
unit            | 
category        | Write-Ahead Log / Settings
short_desc      | Sets the level of information written to the WAL.
extra_desc      | 
context         | postmaster
vartype         | enum
source          | configuration file
min_val         | 
max_val         | 
enumvals        | {minimal,replica,logical}
boot_val        | replica
reset_val       | logical
sourcefile      | /opt/Postgresql/PG_16_3/Data/postgresql.conf
sourceline      | 211
pending_restart | f

4、验证参数max_replication_slots

max_replication_slots必须至少被设置为 1。

czg=# SELECT * FROM PG_CATALOG.PG_SETTINGS WHERE NAME = 'max_replication_slots';
-[ RECORD 1 ]---+---------------------------------------------------------------------
name            | max_replication_slots
setting         | 10
unit            | 
category        | Replication / Sending Servers
short_desc      | Sets the maximum number of simultaneously defined replication slots.
extra_desc      | 
context         | postmaster
vartype         | integer
source          | default
min_val         | 0
max_val         | 262143
enumvals        | 
boot_val        | 10
reset_val       | 10
sourcefile      | 
sourceline      | 
pending_restart | f

5、超级用户连接数据库

czg=# \c
You are now connected to database "czg" as user "postgres".

6、创建逻辑复制槽

czg=# SELECT * FROM PG_CREATE_LOGICAL_REPLICATION_SLOT('czg_slot', 'test_decoding', false, true);
-[ RECORD 1 ]---------
slot_name | czg_slot
lsn       | 0/5985F468
名称描述
slot_name逻辑(解码)复制插槽名
plugin输出插件
temporary当设置为true时,指定插槽不应永久存储到磁盘,仅供当前会话使用。临时插槽也会在任何错误发生时释放。
twophase当设置为true时,指定为此插槽启用已准备事务的解码。

7、查看逻辑复制槽

czg=# SELECT * FROM PG_REPLICATION_SLOTS WHERE SLOT_NAME = 'czg_slot';
-[ RECORD 1 ]-------+--------------
slot_name           | czg_slot
plugin              | test_decoding
slot_type           | logical
datoid              | 16387
database            | czg
temporary           | f
active              | f
active_pid          | 
xmin                | 
catalog_xmin        | 1072
restart_lsn         | 0/5985F430
confirmed_flush_lsn | 0/5985F468
wal_status          | reserved
safe_wal_size       | 
two_phase           | t
conflicting         | f

8、查看逻辑复制槽是否接收到数据变化

czg=# SELECT * FROM PG_LOGICAL_SLOT_GET_CHANGES('czg_slot', NULL, NULL);
(0 rows)
名称描述
slot_name逻辑(解码)复制插槽名。
upto_lsn如果upto_lsn为非 NULL,解码将只包括那些在指定 LSN 之前提交的事务。
upto_nchanges如果upto_nchanges为非 NULL,解码将在其产生的行数超过指定值后停止。
options官方手册中没有解释。

如果upto_lsn和upto_nchanges为 NULL,逻辑解码将一直继续到 WAL 的末尾。 
不过要注意,被返回的实际行数可能更大,因为对这个限制的检查只会在增加了解码每个新的提交事务产生的行之后进行。

因为我们现在还没有做数据改变,所以没有查到数据。

9、建表

czg=# CREATE TABLE TEST (A INT);
CREATE TABLE

10、查看逻辑复制槽是否接收到数据变化

czg=# SELECT * FROM PG_LOGICAL_SLOT_GET_CHANGES('czg_slot', NULL, NULL);
-[ RECORD 1 ]-----
lsn  | 0/5985F4B8
xid  | 1072
data | BEGIN 1072
-[ RECORD 2 ]-----
lsn  | 0/59873558
xid  | 1072
data | COMMIT 1072

DDL 不会被复制,因此只会看到事务。

11、查看逻辑复制槽是否接收到数据变化

czg=# SELECT * FROM PG_LOGICAL_SLOT_GET_CHANGES('czg_slot', NULL, NULL);
(0 rows)

读取更改后,它们将被使用,并且不会在后续调用中发出。

因为我们上面设置的读取到WAL的结尾。

12、插入多条数据

czg=# BEGIN;
BEGIN
czg=*# INSERT INTO TEST VALUES(1);
INSERT 0 1
czg=*# INSERT INTO TEST VALUES(2);
INSERT 0 1
czg=*# COMMIT;
COMMIT

13、查看逻辑复制槽是否接收到数据变化

czg=# SELECT * FROM PG_LOGICAL_SLOT_GET_CHANGES('czg_slot', NULL, NULL);
-[ RECORD 1 ]---------------------------------
lsn  | 0/59873678
xid  | 1073
data | BEGIN 1073
-[ RECORD 2 ]---------------------------------
lsn  | 0/59873678
xid  | 1073
data | table public.test: INSERT: a[integer]:1
-[ RECORD 3 ]---------------------------------
lsn  | 0/598736F0
xid  | 1073
data | table public.test: INSERT: a[integer]:2
-[ RECORD 4 ]---------------------------------
lsn  | 0/59873760
xid  | 1073
data | COMMIT 1073

捕获DML正常。

14、插入数据

czg=# INSERT INTO TEST VALUES(3);
INSERT 0 1

15、逻辑复制槽预读数据变化

czg=# SELECT * FROM PG_LOGICAL_SLOT_PEEK_CHANGES('czg_slot', NULL, NULL);
-[ RECORD 1 ]---------------------------------
lsn  | 0/59873880
xid  | 1074
data | BEGIN 1074
-[ RECORD 2 ]---------------------------------
lsn  | 0/59873880
xid  | 1074
data | table public.test: INSERT: a[integer]:3
-[ RECORD 3 ]---------------------------------
lsn  | 0/59873978
xid  | 1074
data | COMMIT 1074

PG_LOGICAL_SLOT_PEEK_CHANGES函数和PG_LOGICAL_SLOT_GET_CHANGES函数的参数和返回内容一样,只是预读数据变化,可以多次读。

16、options参数改变格式

czg=# SELECT * FROM PG_LOGICAL_SLOT_PEEK_CHANGES('czg_slot', NULL, NULL, 'include-timestamp', 'on');
-[ RECORD 1 ]----------------------------------------
lsn  | 0/59873880
xid  | 1074
data | BEGIN 1074
-[ RECORD 2 ]----------------------------------------
lsn  | 0/59873880
xid  | 1074
data | table public.test: INSERT: a[integer]:3
-[ RECORD 3 ]----------------------------------------
lsn  | 0/59873978
xid  | 1074
data | COMMIT 1074 (at 2024-08-29 17:25:07.957535+08)

17、销毁逻辑复制槽

czg=# SELECT PG_DROP_REPLICATION_SLOT('czg_slot');
-[ RECORD 1 ]------------+-
pg_drop_replication_slot |

四、解码准备好的事务的SQL接口

三中的1-6都需要执行。

1、设置参数max_prepared_transactions

[postgres@czg2 ~]$ cat /opt/Postgresql/PG_16_3/Data/postgresql.conf |grep max_prepared_transactions
max_prepared_transactions = 2           # zero disables the feature
# Caution: it is not advisable to set max_prepared_transactions nonzero unless

max_prepared_transactions至少为1。

2、重启PG

[root@czg2 ~]# service PG_16_3 restart
Restarting PostgreSQL: ok

3、验证参数max_prepared_transactions

czg=# SELECT * FROM PG_CATALOG.PG_SETTINGS WHERE NAME = 'max_prepared_transactions';
-[ RECORD 1 ]---+-----------------------------------------------------------------
name            | max_prepared_transactions
setting         | 2
unit            | 
category        | Resource Usage / Memory
short_desc      | Sets the maximum number of simultaneously prepared transactions.
extra_desc      | 
context         | postmaster
vartype         | integer
source          | configuration file
min_val         | 0
max_val         | 262143
enumvals        | 
boot_val        | 0
reset_val       | 2
sourcefile      | /opt/Postgresql/PG_16_3/Data/postgresql.conf
sourceline      | 137
pending_restart | f

4、逻辑解码提交的准备事务

czg=# \x
Expanded display is on.
czg=# BEGIN;
BEGIN
czg=*# INSERT INTO TEST VALUES(11);
INSERT 0 1
czg=*# PREPARE TRANSACTION 'TEST_PREPARED1';
PREPARE TRANSACTION
czg=# SELECT * FROM PG_LOGICAL_SLOT_PEEK_CHANGES('czg_slot', NULL, NULL);
-[ RECORD 1 ]-----------------------------------------
lsn  | 0/59875048
xid  | 1085
data | BEGIN 1085
-[ RECORD 2 ]-----------------------------------------
lsn  | 0/59875048
xid  | 1085
data | table public.test: INSERT: a[integer]:11
-[ RECORD 3 ]-----------------------------------------
lsn  | 0/59875340
xid  | 1085
data | PREPARE TRANSACTION 'TEST_PREPARED1', txid 1085czg=# COMMIT PREPARED 'TEST_PREPARED1';
COMMIT PREPARED
czg=# SELECT * FROM PG_LOGICAL_SLOT_GET_CHANGES('czg_slot', NULL, NULL);
-[ RECORD 1 ]-----------------------------------------
lsn  | 0/59875048
xid  | 1085
data | BEGIN 1085
-[ RECORD 2 ]-----------------------------------------
lsn  | 0/59875048
xid  | 1085
data | table public.test: INSERT: a[integer]:11
-[ RECORD 3 ]-----------------------------------------
lsn  | 0/59875340
xid  | 1085
data | PREPARE TRANSACTION 'TEST_PREPARED1', txid 1085
-[ RECORD 4 ]-----------------------------------------
lsn  | 0/598753C0
xid  | 1085
data | COMMIT PREPARED 'TEST_PREPARED1', txid 1085czg=# SELECT * FROM TEST WHERE A = 11;
-[ RECORD 1 ]
a | 11

5、逻辑解码回滚的准备事务

czg=# BEGIN;
BEGIN
czg=*# INSERT INTO TEST VALUES(12);
INSERT 0 1
czg=*# PREPARE TRANSACTION 'TEST_PREPARED1';
PREPARE TRANSACTION
czg=# SELECT * FROM PG_LOGICAL_SLOT_PEEK_CHANGES('czg_slot', NULL, NULL);
-[ RECORD 1 ]-----------------------------------------
lsn  | 0/59875880
xid  | 1087
data | BEGIN 1087
-[ RECORD 2 ]-----------------------------------------
lsn  | 0/59875880
xid  | 1087
data | table public.test: INSERT: a[integer]:12
-[ RECORD 3 ]-----------------------------------------
lsn  | 0/598759C0
xid  | 1087
data | PREPARE TRANSACTION 'TEST_PREPARED1', txid 1087czg=# ROLLBACK PREPARED 'TEST_PREPARED1';
ROLLBACK PREPARED
czg=# SELECT * FROM PG_LOGICAL_SLOT_GET_CHANGES('czg_slot', NULL, NULL);
-[ RECORD 1 ]-----------------------------------------
lsn  | 0/59875880
xid  | 1087
data | BEGIN 1087
-[ RECORD 2 ]-----------------------------------------
lsn  | 0/598759C0
xid  | 1087
data | PREPARE TRANSACTION 'TEST_PREPARED1', txid 1087
-[ RECORD 3 ]-----------------------------------------
lsn  | 0/59875A40
xid  | 1087
data | ROLLBACK PREPARED 'TEST_PREPARED1', txid 1087czg=# SELECT * FROM TEST WHERE A = 12;
(0 rows)

回滚准备事务开始之前看到的逻辑解码和之后看到的逻辑解码,少了INSERT语句。

五、逻辑解码插入多列多行

czg=# INSERT INTO TESTTAB(B,C) SELECT 99.1,'SUN_CZG';
INSERT 0 1
czg=# SELECT * FROM PG_LOGICAL_SLOT_GET_CHANGES('czg_slot', NULL, NULL);
-[ RECORD 1 ]------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/5987D7F0
xid  | 1093
data | BEGIN 1093
-[ RECORD 2 ]------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/5987D7F0
xid  | 1093
data | table public.testtab: INSERT: a[integer]:2098670 b[double precision]:99.1 c[character varying]:'SUN_CZG' d[text]:null e[bytea]:null f[bytea]:null g[date]:null h[timestamp without time zone]:null i[numeric]:null
-[ RECORD 3 ]------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/5987D8B8
xid  | 1093
data | COMMIT 1093

看一下解析出的数据,这个输出插件test_decoding编写的已经很好了,但可以稍微压缩一下数据,一个是方便解析,二是减少数据包的大小,减少网络压力。

六、逻辑解码更新多行

czg=# UPDATE TEST SET A = 2 WHERE A < 2;
UPDATE 3
czg=# SELECT * FROM PG_LOGICAL_SLOT_GET_CHANGES('czg_slot', NULL, NULL);
-[ RECORD 1 ]---------------------------------
lsn  | 0/5987D9D8
xid  | 1094
data | BEGIN 1094
-[ RECORD 2 ]---------------------------------
lsn  | 0/5987D9D8
xid  | 1094
data | table public.test: UPDATE: a[integer]:2
-[ RECORD 3 ]---------------------------------
lsn  | 0/5987EA80
xid  | 1094
data | table public.test: UPDATE: a[integer]:2
-[ RECORD 4 ]---------------------------------
lsn  | 0/5987EAC8
xid  | 1094
data | table public.test: UPDATE: a[integer]:2
-[ RECORD 5 ]---------------------------------
lsn  | 0/5987EB40
xid  | 1094
data | COMMIT 1094

解析出的结果,我们不能断定是哪行数据变成为2,这个会影响CDC的实现。

七、逻辑解码删除多行

czg=# DELETE FROM TEST WHERE A <= 2;
DELETE 6
czg=# SELECT * FROM PG_LOGICAL_SLOT_GET_CHANGES('czg_slot', NULL, NULL);
-[ RECORD 1 ]------------------------------------
lsn  | 0/5987EC60
xid  | 1095
data | BEGIN 1095
-[ RECORD 2 ]------------------------------------
lsn  | 0/5987EC60
xid  | 1095
data | table public.test: DELETE: (no-tuple-data)
-[ RECORD 3 ]------------------------------------
lsn  | 0/5987FD28
xid  | 1095
data | table public.test: DELETE: (no-tuple-data)
-[ RECORD 4 ]------------------------------------
lsn  | 0/5987FD60
xid  | 1095
data | table public.test: DELETE: (no-tuple-data)
-[ RECORD 5 ]------------------------------------
lsn  | 0/5987FD98
xid  | 1095
data | table public.test: DELETE: (no-tuple-data)
-[ RECORD 6 ]------------------------------------
lsn  | 0/5987FDD0
xid  | 1095
data | table public.test: DELETE: (no-tuple-data)
-[ RECORD 7 ]------------------------------------
lsn  | 0/5987FE08
xid  | 1095
data | table public.test: DELETE: (no-tuple-data)
-[ RECORD 8 ]------------------------------------
lsn  | 0/5987FE70
xid  | 1095
data | COMMIT 1095

解析出的结果,我们不能断定是哪行数据被删除,这个会影响CDC的实现。

八、逻辑解码COPY

czg=# COPY PUBLIC.TESTTAB(B,C,D,E,F,G,H,I)
czg-#     FROM '/home/postgres/PgData.txt'
czg-# WITH(
czg(# czg(# FORMAT    CSV,
czg(# czg(# DELIMITER '|',
czg(# czg(# NULL      '',
czg(# czg(# QUOTE     '"',
czg(# czg(# ESCAPE    '\');
COPY 10
czg=# SELECT * FROM PG_LOGICAL_SLOT_GET_CHANGES('czg_slot', NULL, NULL);
-[ RECORD 1 ]------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/5987FF90
xid  | 1096
data | BEGIN 1096
-[ RECORD 2 ]------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/5987FFF8
xid  | 1096
data | table public.testtab: INSERT: a[integer]:2098671 b[double precision]:9.1 c[character varying]:'1LXG''ZXJ|"CLX' d[text]:'HAHHAHAH' e[bytea]:'\x41414141
4141' f[bytea]:'\x424242424242424242424242' g[date]:null h[timestamp without time zone]:'2024-08-19 00:00:00' i[numeric]:8.00
-[ RECORD 3 ]------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/5987FFF8
xid  | 1096
data | table public.testtab: INSERT: a[integer]:2098672 b[double precision]:9.1 c[character varying]:'2LXG''ZXJ|"CLX' d[text]:'HAHHAHAH' e[bytea]:'\x41414141
4141' f[bytea]:'\x424242424242424242424242' g[date]:'2024-08-19' h[timestamp without time zone]:'2024-08-19 00:00:00' i[numeric]:8.00
-[ RECORD 4 ]------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/5987FFF8
xid  | 1096
data | table public.testtab: INSERT: a[integer]:2098673 b[double precision]:9.1 c[character varying]:'3LXG''ZXJ|"CLX' d[text]:'HAHHAHAH' e[bytea]:'\x41414141
4141' f[bytea]:'\x424242424242424242424242' g[date]:'2024-08-19' h[timestamp without time zone]:'2024-08-19 00:00:00' i[numeric]:8.00
-[ RECORD 5 ]------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/5987FFF8
xid  | 1096
data | table public.testtab: INSERT: a[integer]:2098674 b[double precision]:9.1 c[character varying]:'4LXG''ZXJ|"CLX' d[text]:'HAHHAHAH' e[bytea]:'\x41414141
4141' f[bytea]:'\x424242424242424242424242' g[date]:'2024-08-19' h[timestamp without time zone]:'2024-08-19 00:00:00' i[numeric]:8.00
-[ RECORD 6 ]------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/5987FFF8
xid  | 1096
data | table public.testtab: INSERT: a[integer]:2098675 b[double precision]:9.1 c[character varying]:'5LXG''ZXJ|"CLX' d[text]:'HAHHAHAH' e[bytea]:'\x41414141
4141' f[bytea]:'\x424242424242424242424242' g[date]:'2024-08-19' h[timestamp without time zone]:'2024-08-19 00:00:00' i[numeric]:8.00
-[ RECORD 7 ]------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/5987FFF8
xid  | 1096
data | table public.testtab: INSERT: a[integer]:2098676 b[double precision]:9.1 c[character varying]:'6LXG''ZXJ|"CLX' d[text]:'HAHHAHAH' e[bytea]:'\x41414141
4141' f[bytea]:'\x424242424242424242424242' g[date]:'2024-08-19' h[timestamp without time zone]:'2024-08-19 00:00:00' i[numeric]:8.00
-[ RECORD 8 ]------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/5987FFF8
xid  | 1096
data | table public.testtab: INSERT: a[integer]:2098677 b[double precision]:9.1 c[character varying]:'7LXG''ZXJ|"CLX' d[text]:'HAHHAHAH' e[bytea]:'\x41414141
4141' f[bytea]:'\x424242424242424242424242' g[date]:'2024-08-19' h[timestamp without time zone]:'2024-08-19 00:00:00' i[numeric]:8.00
-[ RECORD 9 ]------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/5987FFF8
xid  | 1096
data | table public.testtab: INSERT: a[integer]:2098678 b[double precision]:9.1 c[character varying]:'8LXG''ZXJ|"CLX' d[text]:'HAHHAHAH' e[bytea]:'\x41414141
4141' f[bytea]:'\x424242424242424242424242' g[date]:'2024-08-19' h[timestamp without time zone]:'2024-08-19 00:00:00' i[numeric]:8.00
-[ RECORD 10 ]-----------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/59882338
xid  | 1096
data | table public.testtab: INSERT: a[integer]:2098679 b[double precision]:9.1 c[character varying]:'9LXG''ZXJ|"CLX' d[text]:'HAHHAHAH' e[bytea]:'\x41414141
4141' f[bytea]:'\x424242424242424242424242' g[date]:'2024-08-19' h[timestamp without time zone]:'2024-08-19 00:00:00' i[numeric]:8.00
-[ RECORD 11 ]-----------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/59882338
xid  | 1096
data | table public.testtab: INSERT: a[integer]:2098680 b[double precision]:9.1 c[character varying]:'0LXG''ZXJ|"CLX' d[text]:'HAHHAHAH' e[bytea]:'\x41414141
4141' f[bytea]:'\x424242424242424242424242' g[date]:'2024-08-19' h[timestamp without time zone]:'2024-08-19 00:00:00' i[numeric]:8.00
-[ RECORD 12 ]-----------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
lsn  | 0/59882F08
xid  | 1096
data | COMMIT 1096

九、总结

从上面的测试结果来看,如果想用输出插件test_decoding进行逻辑解码来实现CDC,是有一定的问题的,在删除和更新的时候。PG_LOGICAL_SLOT_PEEK_CHANGES支持OPTION选项,来改变一些输出格式,不知道能不能达到想要的效果,主要的问题还是没有找到OPTION相关的介绍,如果大家有了解的欢迎分享。

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

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

相关文章

前后端独立部署的企业级私有化文档管理系统丨无忧·企业文档

大家好&#xff0c;我是软件部长&#xff0c;今天给大家介绍一款企业级在线知识库项目-JVS的无忧企业文档。 JVS提供低代码、物联网、规则引擎、智能BI、逻辑引擎、无忧企业文档&#xff08;在线协同&#xff09;、无忧企业计划、无忧企业邮筒等平台&#xff0c;欢迎关注微信公…

vscode连接不上远程服务器

删除缓存.vscode 然后再删除.ssh

Vue3快熟

Vue3快速上手 1. Vue3简介1.1. 【性能的提升】1.2.【 源码的升级】1.3. 【拥抱TypeScript】1.4. 【新的特性】 2. 创建Vue3工程2.1. 【基于 vue-cli 创建】2.2. 【基于 vite 创建】(推荐)2.3. 【一个简单的效果】 3. Vue3核心语法3.1. 【OptionsAPI 与 CompositionAPI】Options…

【C语言】常见的C语言概念

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. 什么是C语言2.C语言的历史3. 编译器的选择VS20223.1 编译和链接3.2 编译器的对比3.3 VS2022的优缺点 4.VS项目和源文件、头文件介绍5. 第一个C语言程序6. main函数7. printf和库函数8. 关键字介绍9. 字符和ASCII编…

react hooks--useReducer

概述 很多人看到useReducer的第一反应应该是redux的某个替代品&#xff0c;其实并不是 ◼ useReducer仅仅是useState的一种替代方案&#xff1a;  在某些场景下&#xff0c;如果state的处理逻辑比较复杂&#xff0c;我们可以通过useReducer来对其进行拆分&#xff1b; 或…

gma 2.0.13 (2024.09.16) 更新日志

安装 gma 2.0.13 pip install gma2.0.13网盘下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1P0nmZUPMJaPEmYgixoL2QQ?pwd1pc8 提取码&#xff1a;1pc8 注意&#xff1a;此版本没有Linux版&#xff01; 编译gma的Linux虚拟机没有时间修复&#xff0c;本期Linux版…

Angular17+leaflet集成天地图组件

Angular17leaflet集成天地图组件 例图 需要的包 "asymmetrik/ngx-leaflet": "^17.0.0","types/leaflet": "^1.9.12","leaflet": "^1.9.4",去天地图网站获取一个token https://www.tianditu.gov.cn/ 创建Angul…

8、创建一般资产负债科目

定义解释 在前台创建资产负债类科目。定义资产负债类会计科目。 在 SAP 中,会计科目的定义分为两层&#xff1a;科目表层和公司代码层。 比如&#xff1a;一个集团企业可以定义一套会计科目表&#xff0c;但是下面的每个公司代码&#xff0c;从中选择哪些科目&#xff0c;这…

透明LED模块的应用场景

随着科技的不断进步和市场需求的增长&#xff0c;透明LED显示屏的应用越来越广泛&#xff0c;成为了众多领域中的创新亮点。透明LED模块凭借其高通透率、轻薄设计以及与环境的完美融合&#xff0c;正逐步替代传统显示方式&#xff0c;为现代化的展示和广告提供了全新的解决方案…

PicoQuant公司:探索铜铟镓硒(CIGS)太阳能电池技术,引领绿色能源革新

铜铟镓硒&#xff08;‌CIGS&#xff09;‌薄膜太阳能电池具有生产成本低、污染小、不衰退、弱光性能好等显著特点&#xff0c;光电转换效率居各种薄膜太阳电池之首&#xff0c;接近于晶体硅太阳电池&#xff0c;而成本只是它的三分之一&#xff0c;被称为下一代非常有前途的新…

window批处理脚本:将本地的三个文件通过SCP传输到Linux设备上

文件名send_file.bat&#xff1a; echo off setlocal:: 提示用户输入远程IP地址 set /p remoteIpAddressplease input IP::: 定义本地文件名 set "localFile1111" set "localFile2222" set "localFile3333":: 获取本地文件的完整路径 set "…

项目与产品的生命周期

在项目管理领域有两个关键概念&#xff0c;即项目生命周期和产品生命周期。它们是理解项目管理过程中的关键要素。 项目生命周期是一个项目从概念到完成所经过的所有阶段。所有项目都可分成若干阶段&#xff0c;且所有项目无论大小&#xff0c;都有一个类似的生命周期结构。阶…

学习大数据DAY59 全量抽取和增量抽取实战

目录 需求流程&#xff1a; 需求分析与规范 作业 作业2 需求流程&#xff1a; 全量抽取 增量抽取 - DataX Kettle Sqoop ... 场景: 业务部门同事或者甲方的工作人员给我们的部门经理和你提出了新的需 求 流程: 联系 > 开会讨论 > 确认需求 > 落地 需求文档( 具体…

day-56 整数转罗马数字

思路 因为题目已经告知num<3999&#xff0c;所以只需依次对1000,900,500,400,100,90,50,40,10,9,5,4,1这些数进行除法&#xff0c;判断商是否大于等于1&#xff0c;如果大于等于1则将对应的罗马数字拼接到字符串中即可 解题过程 为了方便拼接&#xff0c;可以使用哈希键值对…

关于用matplotlib.pyplot加载图片颜色不对的解决方法

1.原理&#xff1a;用opencv加载的图片是BGR存储的。而用matplotlib.pyplot 需要RGB的格式,故在加载之前使用下面的语句改成RGB格式。 img2 cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 或使用 # img2 img[:, :, ::-1]#将图像img的颜色通道进行反转。 ::-1 表示在最后一个维度…

【吊打面试官系列-MySQL面试题】LIKE 声明中的%和_是什么意思?

大家好&#xff0c;我是锋哥。今天分享关于【LIKE 声明中的&#xff05;和_是什么意思&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; LIKE 声明中的&#xff05;和_是什么意思&#xff1f; &#xff05;对应于 0 个或更多字符&#xff0c;_只是 LIKE 语句中的…

图纸管理系统到底是什么?适合哪些企业去部署?

图纸管理系统作为现代企业数字化转型的基石&#xff0c;正逐步成为各行各业不可或缺的重要工具。它不仅革新了传统图纸的存储与管理方式&#xff0c;更通过集成化、智能化的功能&#xff0c;为企业带来了前所未有的工作效率与数据安全保障。无论是建筑设计、制造业还是航空航天…

Prometheus架构详解

1 Prometheus简介 Prometheus 是一个开源的系统监控报警工具套件&#xff0c;它最初由SoundCloud开发&#xff0c;并于2016年成为CNCF&#xff08;云原生计算基金会&#xff09;托管的第二个项目&#xff08;第一个是kubernetes&#xff09;。Prometheus 以其简单高效的方式收…

华为云服务综合实验

一、实验需求 本次实验内容基于华为云平台模拟企业web集群的构建&#xff0c;其中涉及的知识点包括Linux系统知识、nginx服务的安装及配置应用、云数据库 RDS(Relational Database Service,简称RDS)、虚拟私有云vpc、安全组、SFS弹性文件服务器以及负载均衡等。要求学生通过本…

基于SSM的“大学生兼职平台”的设计与实现(源码+数据库+文档+开题报告)

基于SSM的“大学生兼职平台”的设计与实现&#xff08;源码数据库文档开题报告) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统结构图 兼职平台首页 企业信息 用户注册界面 在线留…