PostgreSQL的學習心得和知識總結(一百四十七)|深入理解PostgreSQL數據庫之transaction chain的使用和實現


注:提前言明 本文借鑒了以下博主、書籍或網站的內容,其列表如下:

1、參考書籍:《PostgreSQL數據庫內核分析》
2、參考書籍:《數據庫事務處理的藝術:事務管理與并發控制》
3、PostgreSQL數據庫倉庫鏈接,點擊前往
4、日本著名PostgreSQL數據庫專家 鈴木啟修 網站主頁,點擊前往
5、參考書籍:《PostgreSQL中文手冊》
6、參考書籍:《PostgreSQL指南:內幕探索》,點擊前往
7、Using Transaction Chaining to Reduce Server Round-Trips,點擊前往


1、本文內容全部來源于開源社區 GitHub和以上博主的貢獻,本文也免費開源(可能會存在問題,評論區等待大佬們的指正)
2、本文目的:開源共享 拋磚引玉 一起學習
3、本文不提供任何資源 不存在任何交易 與任何組織和機構無關
4、大家可以根據需要自行 復制粘貼以及作為其他個人用途,但是不允許轉載 不允許商用 (寫作不易,還請見諒 💖)
5、本文內容基于PostgreSQL master源碼開發而成


深入理解PostgreSQL數據庫之transaction chain的使用和實現

  • 文章快速說明索引
  • 功能使用背景說明
  • 功能實現源碼分析
  • 源碼調試案例分析



文章快速說明索引

學習目標:

做數據庫內核開發久了就會有一種 少年得志,年少輕狂 的錯覺,然鵝細細一品覺得自己其實不算特別優秀 遠遠沒有達到自己想要的。也許光鮮的表面掩蓋了空洞的內在,每每想到于此,皆有夜半臨淵如履薄冰之感。為了睡上幾個踏實覺,即日起 暫緩其他基于PostgreSQL數據庫的兼容功能開發,近段時間 將著重于學習分享Postgres的基礎知識和實踐內幕。


學習內容:(詳見目錄)

1、深入理解PostgreSQL數據庫之transaction chain的使用和實現


學習時間:

2024年07月01日 20:25:11


學習產出:

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>

功能使用背景說明

使用 PostgreSQL 或任何關系數據庫實現業務應用程序通常相當于執行一系列事務。給定事務以 COMMIT 還是 ROLLBACK 結束并不重要,因為在這兩種情況下,下一個事務都會在前一個事務完成后立即開始。此外,對于大多數應用程序來說,前一個事務和下一個事務具有相似的特征,例如它們的 ISOLATION LEVEL。本質上,您最終得到的樣式如下所示:

START TRANSACTION;
-- workload of 1st transaction
COMMIT;
START TRANSACTION;
-- workload of 2nd transaction
ROLLBACK;
START TRANSACTION;
-- workload of 3rd transaction
COMMIT;

在上面的 SQL 腳本中,您會看到三個后續事務和總共六個語句(每個事務兩個語句),但您可以想象更長的事務序列。問題是:每個語句都需要單獨的服務器往返才能執行。沒有辦法解決這個問題,即使三個示例事務為空(不包含任何語句),也沒有什么區別。


監控連接狀態

為了進行此實驗,我們需要與同一 PostgreSQL 服務器建立兩個單獨的連接(例如,兩個 psql 會話)。第一個連接使用 postgres 數據庫,第二個連接使用demo數據庫。

好了,現在我們可以在第一個連接上使用 pg_stat_activity(屬于 pg_catalog 模式的內置視圖)來詢問 PostgreSQL 使用演示數據庫的第二個連接的狀態:

postgres=# SELECT state FROM pg_stat_activity WHERE datname='demo';state
-------idle
(1 row)

如您所見,由于沒有執行任何操作,因此該連接當前處于空閑狀態。但是,如果我們在第二個連接上啟動事務,我們可以看到連接的狀態立即變為idle in transaction

demo=# START TRANSACTION;
START TRANSACTION
postgres=# SELECT state FROM pg_stat_activity WHERE datname='demo';state
---------------------idle in transaction
(1 row)

這證明 START TRANSACTION 語句導致了與服務器的往返,因為如果沒有,第一個連接將無法看到第二個連接的狀態變化。如果我們使用 COMMITROLLBACK 完成事務,情況也是一樣的,在這種情況下,連接會立即恢復到空閑狀態:

demo=*# COMMIT;
COMMIT
postgres=# SELECT state FROM pg_stat_activity WHERE datname='demo';state
-------idle
(1 row)

往返開銷

長話短說,事務的開始和結束可能會帶來巨大的開銷。具體來說,如果滿足以下任何條件:

  1. 往返服務器的時間很慢。通常,如果客戶端和服務器之間的網絡距離很遠,情況就會如此。
  2. 許多事務的平均運行時間很短。這是因為對于較短的事務,開銷占總運行時間的百分比較高。

那么,我們可以做些什么來減少開銷并提高性能呢?


事務鏈

SQL 標準有一個由 PostgreSQL 實現的內置解決方案:AND CHAIN 參數。此參數可用于 COMMITROLLBACK 語句,并具有以下效果…

如果提供了 AND CHAIN 參數,則提交(或回滾)當前事務,此外,立即啟動具有相同特征(例如,ISOLATION LEVEL)的后續事務。

因此,如果我們將其應用于原始示例,我們可以將服務器往返次數減少基本上 50%(從 n 減少到 n/2+1)。

START TRANSACTION;
-- workload of 1st transaction
COMMIT AND CHAIN;
-- workload of 2nd transaction
ROLLBACK AND CHAIN;
-- workload of 3rd transaction
COMMIT;

我們可以運行相同的實驗來證明它按預期工作。我再次使用兩個連接,一個使用 postgres 數據庫,另一個使用演示數據庫。最初,演示連接處于空閑狀態,但是一旦我們開始新的事務,其狀態就會更改為idle in transaction

demo=# START TRANSACTION;
START TRANSACTION
postgres=# SELECT state FROM pg_stat_activity WHERE datname='demo';state
---------------------idle in transaction
(1 row)

那么,如果demo連接執行 COMMIT AND CHAIN 語句會發生什么?正如我所說,PostgreSQL 立即啟動后續事務,因此我們看不到狀態變化。

demo=# COMMIT AND CHAIN;
COMMIT AND CHAIN
postgres=# SELECT state FROM pg_stat_activity WHERE datname='demo';state
---------------------idle in transaction
(1 row)

當我們執行 ROLLBACK AND CHAIN 時,我們得到完全相同的行為 — 沒有明顯的狀態改變。

demo=# ROLLBACK AND CHAIN;
ROLLBACK AND CHAIN
postgres=# SELECT state FROM pg_stat_activity WHERE datname='demo';state
---------------------idle in transaction
(1 row)

最后,當我們發出正常的COMMITROLLBACK時,狀態就會變回初始的空閑狀態。

demo=# COMMIT;
COMMIT
postgres=# SELECT state FROM pg_stat_activity WHERE datname='demo';state
-------idle
(1 row)

功能實現源碼分析

其語法格式如下:

// src/backend/parser/gram.y/*******************************************************************************		Transactions:**		BEGIN / COMMIT / ROLLBACK*		(also older versions END / ABORT)******************************************************************************/TransactionStmt:ABORT_P opt_transaction opt_transaction_chain{TransactionStmt *n = makeNode(TransactionStmt);n->kind = TRANS_STMT_ROLLBACK;n->options = NIL;n->chain = $3;n->location = -1;$$ = (Node *) n;}...| COMMIT opt_transaction opt_transaction_chain{TransactionStmt *n = makeNode(TransactionStmt);n->kind = TRANS_STMT_COMMIT;n->options = NIL;n->chain = $3;n->location = -1;$$ = (Node *) n;}| ROLLBACK opt_transaction opt_transaction_chain{TransactionStmt *n = makeNode(TransactionStmt);n->kind = TRANS_STMT_ROLLBACK;n->options = NIL;n->chain = $3;n->location = -1;$$ = (Node *) n;}...;TransactionStmtLegacy:...| END_P opt_transaction opt_transaction_chain{TransactionStmt *n = makeNode(TransactionStmt);n->kind = TRANS_STMT_COMMIT;n->options = NIL;n->chain = $3;n->location = -1;$$ = (Node *) n;};opt_transaction_chain:AND CHAIN		{ $$ = true; }| AND NO CHAIN	{ $$ = false; }| /* EMPTY */	{ $$ = false; };

示例一,如下:

在這里插入圖片描述
在這里插入圖片描述


示例二,如下:

在這里插入圖片描述
在這里插入圖片描述


源碼調試案例分析

接下來,我們調試一下 重點看一下上面的示例二,如下:

在這里插入圖片描述

如上,begin READ ONLY;是在上圖將guc參數transaction_read_only設置為真 XactReadOnly = true,函數堆棧,如下:

set_config_with_handle(const char * name, config_handle * handle, const char * value, GucContext context, GucSource source, Oid srole, GucAction action, _Bool changeVal, int elevel, _Bool is_reload) (\home\postgres\postgres\src\backend\utils\misc\guc.c:3758)
set_config_option(const char * name, const char * value, GucContext context, GucSource source, GucAction action, _Bool changeVal, int elevel, _Bool is_reload) (\home\postgres\postgres\src\backend\utils\misc\guc.c:3361)
SetPGVariable(const char * name, List * args, _Bool is_local) (\home\postgres\postgres\src\backend\utils\misc\guc_funcs.c:320)
standard_ProcessUtility(PlannedStmt * pstmt, const char * queryString, _Bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment * queryEnv, DestReceiver * dest, QueryCompletion * qc) (\home\postgres\postgres\src\backend\tcop\utility.c:619)
ProcessUtility(PlannedStmt * pstmt, const char * queryString, _Bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment * queryEnv, DestReceiver * dest, QueryCompletion * qc) (\home\postgres\postgres\src\backend\tcop\utility.c:523)
PortalRunUtility(Portal portal, PlannedStmt * pstmt, _Bool isTopLevel, _Bool setHoldSnapshot, DestReceiver * dest, QueryCompletion * qc) (\home\postgres\postgres\src\backend\tcop\pquery.c:1158)
PortalRunMulti(Portal portal, _Bool isTopLevel, _Bool setHoldSnapshot, DestReceiver * dest, DestReceiver * altdest, QueryCompletion * qc) (\home\postgres\postgres\src\backend\tcop\pquery.c:1315)
PortalRun(Portal portal, long count, _Bool isTopLevel, _Bool run_once, DestReceiver * dest, DestReceiver * altdest, QueryCompletion * qc) (\home\postgres\postgres\src\backend\tcop\pquery.c:791)
exec_simple_query(const char * query_string) (\home\postgres\postgres\src\backend\tcop\postgres.c:1274)
PostgresMain(const char * dbname, const char * username) (\home\postgres\postgres\src\backend\tcop\postgres.c:4680)
BackendMain(char * startup_data, size_t startup_data_len) (\home\postgres\postgres\src\backend\tcop\backend_startup.c:105)
postmaster_child_launch(BackendType child_type, char * startup_data, size_t startup_data_len, ClientSocket * client_sock) (\home\postgres\postgres\src\backend\postmaster\launch_backend.c:265)
BackendStartup(ClientSocket * client_sock) (\home\postgres\postgres\src\backend\postmaster\postmaster.c:3593)
ServerLoop() (\home\postgres\postgres\src\backend\postmaster\postmaster.c:1674)
PostmasterMain(int argc, char ** argv) (\home\postgres\postgres\src\backend\postmaster\postmaster.c:1372)
main(int argc, char ** argv) (\home\postgres\postgres\src\backend\main\main.c:197)

接下來,這里將直接INSERT,報錯如下:

在這里插入圖片描述

后續處理,如下:

在這里插入圖片描述

此時的函數堆棧,如下:

AtEOXact_GUC(_Bool isCommit, int nestLevel)
AbortTransaction()
AbortCurrentTransactionInternal()
AbortCurrentTransaction()
PostgresMain(const char * dbname, const char * username)
BackendMain(char * startup_data, size_t startup_data_len)
postmaster_child_launch(BackendType child_type, char * startup_data, size_t startup_data_len, ClientSocket * client_sock)
BackendStartup(ClientSocket * client_sock)
ServerLoop()
PostmasterMain(int argc, char ** argv)
main(int argc, char ** argv)

注:如上 在INSERT報錯之后,該事務對應的上述GUC被重置,如下:

// src/backend/utils/misc/guc.c/** Do GUC processing at transaction or subtransaction commit or abort, or* when exiting a function that has proconfig settings, or when undoing a* transient assignment to some GUC variables.  (The name is thus a bit of* a misnomer; perhaps it should be ExitGUCNestLevel or some such.)* During abort, we discard all GUC settings that were applied at nesting* levels >= nestLevel.  nestLevel == 1 corresponds to the main transaction.*  * 在事務或子事務提交或中止時,或在退出具有 proconfig 設置的函數時,或在撤消對某些 GUC 變量的臨時分配時,執行 GUC 處理* (因此,這個名字有點用詞不當;也許應該是 ExitGUCNestLevel 或類似的名字)* 在中止期間,我們會丟棄在嵌套級別 >= nestLevel 處應用的所有 GUC 設置* nestLevel == 1 對應于主事務*/
void
AtEOXact_GUC(bool isCommit, int nestLevel);

于是在接下來的commit and chain;中,XactReadOnly仍是假,如下:

在這里插入圖片描述

此時函數堆棧,如下:

EndTransactionBlock(_Bool chain)
standard_ProcessUtility(PlannedStmt * pstmt, const char * queryString, _Bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment * queryEnv, DestReceiver * dest, QueryCompletion * qc)
ProcessUtility(PlannedStmt * pstmt, const char * queryString, _Bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment * queryEnv, DestReceiver * dest, QueryCompletion * qc)
PortalRunUtility(Portal portal, PlannedStmt * pstmt, _Bool isTopLevel, _Bool setHoldSnapshot, DestReceiver * dest, QueryCompletion * qc) 
PortalRunMulti(Portal portal, _Bool isTopLevel, _Bool setHoldSnapshot, DestReceiver * dest, DestReceiver * altdest, QueryCompletion * qc)
PortalRun(Portal portal, long count, _Bool isTopLevel, _Bool run_once, DestReceiver * dest, DestReceiver * altdest, QueryCompletion * qc)
exec_simple_query(const char * query_string)
...

接下來,我們調試一下上面的示例二的另一種情況,因為當前會話已經設置該GUC參數為真(將要被rollback或者commit的事務),接下來的rollback and chain的處理 如下:

在這里插入圖片描述

UserAbortTransactionBlock(_Bool chain) (\home\postgres\postgres\src\backend\access\transam\xact.c:4262)
standard_ProcessUtility(PlannedStmt * pstmt, const char * queryString, _Bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment * queryEnv, DestReceiver * dest, QueryCompletion * qc)
ProcessUtility(PlannedStmt * pstmt, const char * queryString, _Bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment * queryEnv, DestReceiver * dest, QueryCompletion * qc)
PortalRunUtility(Portal portal, PlannedStmt * pstmt, _Bool isTopLevel, _Bool setHoldSnapshot, DestReceiver * dest, QueryCompletion * qc)
PortalRunMulti(Portal portal, _Bool isTopLevel, _Bool setHoldSnapshot, DestReceiver * dest, DestReceiver * altdest, QueryCompletion * qc)
PortalRun(Portal portal, long count, _Bool isTopLevel, _Bool run_once, DestReceiver * dest, DestReceiver * altdest, QueryCompletion * qc)
exec_simple_query(const char * query_string)
...

在UserAbortTransactionBlock函數中的處理,如下:

s->blockState: TBLOCK_INPROGRESS -> TBLOCK_ABORT_PENDING
s->chain: false -> true

然后進入如下的處理邏輯:

CommitTransactionCommandInternal()
CommitTransactionCommand()
finish_xact_command()
exec_simple_query(const char * query_string)
...
			/** Here we were in a perfectly good transaction block but the user* told us to ROLLBACK anyway.  We have to abort the transaction* and then clean up.*/case TBLOCK_ABORT_PENDING:AbortTransaction();CleanupTransaction();s->blockState = TBLOCK_DEFAULT;if (s->chain){StartTransaction();s->blockState = TBLOCK_INPROGRESS;s->chain = false;RestoreTransactionCharacteristics(&savetc);}break;

首先進入AbortTransaction函數,因為在這種情況下guc_stack_list != NIL,在如下的堆棧處理中 該參數XactReadOnly被置為假:

AtEOXact_GUC(_Bool isCommit, int nestLevel)
AbortTransaction()
CommitTransactionCommandInternal()
CommitTransactionCommand()
finish_xact_command()
exec_simple_query(const char * query_string)
...

在這里插入圖片描述


接著進入CleanupTransaction函數進行清理!


接下來進入今天的重點,如下:

			if (s->chain){StartTransaction();s->blockState = TBLOCK_INPROGRESS;s->chain = false;RestoreTransactionCharacteristics(&savetc);}

因為chain為真,這里還是再重啟一個事務。不過這種類似于XactReadOnly的guc參數在StartTransaction過程中仍被賦值默認值!該參數的重新修改如下:

在這里插入圖片描述

至此,rollback and chain 操作回滾了上一個事務,并開啟新的事務 且XactReadOnly = true,得以保留!


同上面rollback and chain操作一樣,其他幾種 如下:

// src/backend/access/transam/xact.c/**	CommitTransactionCommandInternal - a function doing an iteration of work*		regarding handling the commit transaction command.  In the case of*		subtransactions more than one iterations could be required.  Returns*		true when no more iterations required, false otherwise.*/
static bool
CommitTransactionCommandInternal(void)
{.../** We are completing a "COMMIT" command.  Do it and return to the* idle state.*/case TBLOCK_END:CommitTransaction();s->blockState = TBLOCK_DEFAULT;if (s->chain)				// here{StartTransaction();s->blockState = TBLOCK_INPROGRESS;s->chain = false;RestoreTransactionCharacteristics(&savetc);}break;.../** Here we were in an aborted transaction block and we just got* the ROLLBACK command from the user, so clean up the* already-aborted transaction and return to the idle state.*/case TBLOCK_ABORT_END:CleanupTransaction();s->blockState = TBLOCK_DEFAULT;if (s->chain)				// here{StartTransaction();s->blockState = TBLOCK_INPROGRESS;s->chain = false;RestoreTransactionCharacteristics(&savetc);}break;.../** Here we were in a perfectly good transaction block but the user* told us to ROLLBACK anyway.  We have to abort the transaction* and then clean up.*/case TBLOCK_ABORT_PENDING:AbortTransaction();CleanupTransaction();s->blockState = TBLOCK_DEFAULT;if (s->chain)				// here{StartTransaction();s->blockState = TBLOCK_INPROGRESS;s->chain = false;RestoreTransactionCharacteristics(&savetc);}break;.../** The user issued a COMMIT, so we end the current subtransaction* hierarchy and perform final commit. We do this by rolling up* any subtransactions into their parent, which leads to O(N^2)* operations with respect to resource owners - this isn't that* bad until we approach a thousands of savepoints but is* necessary for correctness should after triggers create new* resource owners.*/case TBLOCK_SUBCOMMIT:do{CommitSubTransaction();s = CurrentTransactionState;	/* changed by pop */} while (s->blockState == TBLOCK_SUBCOMMIT);/* If we had a COMMIT command, finish off the main xact too */if (s->blockState == TBLOCK_END){Assert(s->parent == NULL);CommitTransaction();s->blockState = TBLOCK_DEFAULT;if (s->chain)				// here{StartTransaction();s->blockState = TBLOCK_INPROGRESS;s->chain = false;RestoreTransactionCharacteristics(&savetc);}}else if (s->blockState == TBLOCK_PREPARE){Assert(s->parent == NULL);PrepareTransaction();s->blockState = TBLOCK_DEFAULT;}elseelog(ERROR, "CommitTransactionCommand: unexpected state %s",BlockStateAsString(s->blockState));break;...
}

對應非特殊的guc參數,能否可以繼承呢?如下:

[postgres@localhost:~/test/bin]$ ./psql 
psql (17beta2)
Type "help" for help.postgres=# show timezone;TimeZone       
---------------------America/Los_Angeles
(1 row)postgres=# begin;
BEGIN
postgres=*# set timezone = 'PRC';
SET
postgres=*# show timezone;TimeZone 
----------PRC
(1 row)postgres=*# commit and chain; ## commit 提交 && 繼承
COMMIT
postgres=*# show timezone;TimeZone 
----------PRC
(1 row)postgres=*# rollback and chain; ## 無東西可以回滾
ROLLBACK
postgres=*# show timezone;TimeZone 
----------PRC
(1 row)postgres=*#
[postgres@localhost:~/test/bin]$ ./psql 
psql (17beta2)
Type "help" for help.postgres=# show timezone;TimeZone       
---------------------America/Los_Angeles
(1 row)postgres=# begin;
BEGIN
postgres=*# desc a error;
2024-07-01 06:19:56.969 PDT [34810] ERROR:  syntax error at or near "desc" at character 1
2024-07-01 06:19:56.969 PDT [34810] STATEMENT:  desc a error;
ERROR:  syntax error at or near "desc"
LINE 1: desc a error;^
postgres=!# show timezone;
2024-07-01 06:20:00.721 PDT [34810] ERROR:  current transaction is aborted, commands ignored until end of transaction block
2024-07-01 06:20:00.721 PDT [34810] STATEMENT:  show timezone;
ERROR:  current transaction is aborted, commands ignored until end of transaction block
postgres=!# 
postgres=!# commit and chain; ## commit 這里相當于先回滾 && 繼承
ROLLBACK
postgres=*# show timezone;TimeZone       
---------------------America/Los_Angeles
(1 row)postgres=*# set timezone = 'PRC';
SET
postgres=*# show timezone;TimeZone 
----------PRC
(1 row)postgres=*# commit and chain; ## commit 提交 && 繼承
COMMIT
postgres=*# show timezone;TimeZone 
----------PRC
(1 row)postgres=*# rollback and chain; ## 無東西可以回滾
ROLLBACK
postgres=*# show timezone;TimeZone 
----------PRC
(1 row)postgres=*# reset timezone;
RESET
postgres=*# show timezone;TimeZone       
---------------------America/Los_Angeles
(1 row)postgres=*# rollback and chain; ## rollback 這里相當于先回滾 && 繼承
ROLLBACK
postgres=*# show timezone;TimeZone 
----------PRC
(1 row)postgres=*#

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

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

相關文章

2024年文化傳播與對外交流國際學術會議(ICCCFE 2024)

2024年文化傳播與對外交流國際學術會議(ICCCFE 2024) 2024 International Conference on Cultural Communication and Foreign Exchange(ICCCFE 2024) 會議簡介: 2024年文化傳播與對外交流國際學術會議(ICCCFE 2024)定…

clion開發51 沒有創建成功可能是Clion版本問題

安裝插件 PlatformlO for CLion 進入這個網站下載get-platformio.py https://docs.platformio.org/en/latest/core/installation/methods/installer-script.html#local-download-macos-linux-windows 點擊 Installation Methods 選擇 Local Download (macOS/Linux/Windows) 點…

linux指令gzip

gzip 是 Linux 系統中廣泛使用的一個文件壓縮和解壓縮程序。它使用 Lempel-Ziv 編碼(LZ77)和 Huffman 編碼的組合來壓縮文件,減少磁盤使用空間和網絡傳輸時間。以下是對 gzip 命令的一些基本使用說明和示例,這些示例旨在幫助你了解…

小阿軒yx-案例:MySQL主從復制與讀寫分離

小阿軒yx-案例:MySQL主從復制與讀寫分離 案例分析 概述 實際生產環境中 如果對數據庫讀和寫都在同一個數據庫服務器中操作,無論在安全性、高可用性還是高并發等各個方面都完全不能滿足實際需求一般都是通過主從復制(Master-Slave&#xf…

MSPG3507——藍牙接收數據顯示在OLED,滴答定時器延時500MS

#include "ti_msp_dl_config.h" #include "OLED.h" #include "stdio.h"volatile unsigned int delay_times 0;//搭配滴答定時器實現的精確ms延時 void delay_ms(unsigned int ms) {delay_times ms;while( delay_times ! 0 ); } int a0; …

4.自動生成class和device

第三章里面,我們使用mknod創建設備節點,常規操作是在驅動init的時候就創建好,使用class_create和device_create創建。 #include "asm/uaccess.h" #include "linux/scatterlist.h" #include "linux/types.h" #…

【公平鎖 和 非公平鎖】

公平鎖 和 非公平鎖 公平鎖:類似食堂打飯,按照申請鎖的順序來獲取鎖類似廁所蹲坑先來后到 公平鎖就是很公平 在并發環境下每個線程在獲取鎖的同時會先查看此鎖維護的等待隊列,如果為空,或者當前線程是等待就占有鎖,否則就加入到…

20人團隊如何免費使用 Atlassian 云產品?

企業賺錢越來越難,尤其是初創團隊或小型團隊更傾向于使用免費工具支持業務。團隊規模影響協作復雜度,Atlassian 考慮到小團隊的需求,提供了多種選擇。比如,Jira 和 Confluence 的云版本有免費版,包含基本的項目管理功能…

ISP IC/FPGA設計-第一部分-SC130GS攝像頭分析(0)

1.介紹 SC130GS是一款國產的Global shutter CMOS圖像傳感器,最高支持1280Hx1024V240fps的傳輸速率;SC130GS有黑白和彩色款,作為ISP開發選擇彩色的,有效像素窗口為1288Hx1032V,支持復雜的片上操作,選擇他理…

Toshiba東芝TB6612FNG電機驅動IC:釋放性能與多功能性

在嵌入式系統和機器人技術領域,電機控制是一個關鍵方面,對項目的性能和可靠性有著顯著影響。東芝的TB6612FNG電機驅動IC作為一個穩健且多功能的解決方案,在驅動雙直流電機方面脫穎而出,提供了高性能、可靠性和易用性。本文將深入探…

23種設計模式之裝飾者模式

深入理解裝飾者模式 一、裝飾者模式簡介1.1 定義1.2 模式類型1.3 主要作用1.4 優點1.5 缺點 二、模式動機三、模式結構四、 裝飾者模式的實現4.1 組件接口4.2 具體組件4.3 裝飾者抽象類4.4 具體裝飾者4.5 使用裝飾者模式4.6 輸出結果: 五、 應用場景5.1 圖形用戶界面…

排序(堆排序、快速排序、歸并排序)-->深度剖析(二)

前言 前面介紹了冒泡排序、選擇排序、插入排序、希爾排序,作為排序中經常用到了算法,還有堆排序、快速排序、歸并排序 堆排序(HeaSort) 堆排序的概念 堆排序是一種有效的排序算法,它利用了完全二叉樹的特性。在C語言…

復分析——第9章——橢圓函數導論(E.M. Stein R. Shakarchi)

第 9 章 橢圓函數導論 (An Introduction to Elliptic Functions) The form that Jacobi had given to the theory of elliptic functions was far from perfection; its flaws are obvious. At the base we find three fundamental functions sn, cn and dn. These functio…

商湯上海AI實驗室聯合發布:自動駕駛全棧式高精度標定工具箱(含車、IMU、相機、激光雷達等的標定)

前言 在自動駕駛技術飛速發展的今天,傳感器的精確標定對于確保系統性能至關重要。SensorsCalibration,一個專為自動駕駛車輛設計的標定工具箱,提供了一套全面的解決方案,用于校準包括IMU、激光雷達、攝像頭和雷達在內的多種傳感器…

基于Java平價平價汽車租賃系統設計和實現(源碼+LW+部署講解)

💗博主介紹:?全網粉絲10W,CSDN作者、博客專家、全棧領域優質創作者,博客之星、平臺優質作者、專注于Java、小程序技術領域和畢業項目實戰?💗 🌟文末獲取源碼數據庫🌟 感興趣的可以先收藏起來,…

【python】使用conda管理python項目:conda管理不同項目環境,pip下載最新的包

文章目錄 一. python包管理概述1. miniforge、Miniconda與Anaconda2. conda與pip的區別是什么?3. pip與conda配合使用 二. 使用conda管理不同py環境1. 創建一個環境2. 解決沖突 三. 命令合集1. conda1.1. 常用1.2. 環境管理1.3. 分享環境1.4. 包管理 2. 依賴沒有在c…

《RepViT Revisiting Mobile CNN From ViT Perspective》

期刊:CVPR 年份:2024 代碼:http://https: //github.com/THU-MIG/RepViT 摘要 最近,與輕量級卷積神經網絡(CNN)相比,輕量級視覺Transformer(ViTs)在資源受限的移動設備上表現出了更高的性能和更低的延遲。研究人員已…

無法訪問指向的web服務器(或虛擬主機)的目錄,請檢查網絡設置

微信公眾平臺,進行業務域名、JS接口安全域名、網頁授權域名配置時,遇到的問題中有:無法訪問指向的web服務器(或虛擬主機)的目錄,請檢查網絡設置,這里簡單記錄一下處理過程。 關于這個問題首先保證下載…

SHELL腳本學習(十四)gawk進階

一、使用變量 gawk支持兩種變量 內建變量自定義變量 1.1 內建變量 1.1.1 字段和記錄分隔符變量 數據字段變量允許使用美元符號 $ 和 位置來引用對應的字段。 $1 對應第一個數據字段,$2對應第二個數據字段,以此類推。 數據字段用字段分隔符劃定。默…