中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

彩票做的最好是個(gè)網(wǎng)站好佛山seo培訓(xùn)機(jī)構(gòu)

彩票做的最好是個(gè)網(wǎng)站好,佛山seo培訓(xùn)機(jī)構(gòu),wordpress本地訪問慢,微信網(wǎng)站推廣目錄結(jié)構(gòu) 注:提前言明 本文借鑒了以下博主、書籍或網(wǎng)站的內(nèi)容,其列表如下: 1、參考書籍:《PostgreSQL數(shù)據(jù)庫內(nèi)核分析》 2、參考書籍:《數(shù)據(jù)庫事務(wù)處理的藝術(shù):事務(wù)管理與并發(fā)控制》 3、PostgreSQL數(shù)據(jù)庫倉庫…

注:提前言明 本文借鑒了以下博主、書籍或網(wǎng)站的內(nèi)容,其列表如下:

1、參考書籍:《PostgreSQL數(shù)據(jù)庫內(nèi)核分析》
2、參考書籍:《數(shù)據(jù)庫事務(wù)處理的藝術(shù):事務(wù)管理與并發(fā)控制》
3、PostgreSQL數(shù)據(jù)庫倉庫鏈接,點(diǎn)擊前往
4、日本著名PostgreSQL數(shù)據(jù)庫專家 鈴木啟修 網(wǎng)站主頁,點(diǎn)擊前往
5、參考書籍:《PostgreSQL中文手冊(cè)》
6、參考書籍:《PostgreSQL指南:內(nèi)幕探索》,點(diǎn)擊前往


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


深入理解PostgreSQL數(shù)據(jù)庫之Support event trigger for logoff

  • 文章快速說明索引
  • 功能使用背景說明
  • 補(bǔ)丁實(shí)現(xiàn)原理分析



文章快速說明索引

學(xué)習(xí)目標(biāo):

做數(shù)據(jù)庫內(nèi)核開發(fā)久了就會(huì)有一種 少年得志,年少輕狂 的錯(cuò)覺,然鵝細(xì)細(xì)一品覺得自己其實(shí)不算特別優(yōu)秀 遠(yuǎn)遠(yuǎn)沒有達(dá)到自己想要的。也許光鮮的表面掩蓋了空洞的內(nèi)在,每每想到于此,皆有夜半臨淵如履薄冰之感。為了睡上幾個(gè)踏實(shí)覺,即日起 暫緩其他基于PostgreSQL數(shù)據(jù)庫的兼容功能開發(fā),近段時(shí)間 將著重于學(xué)習(xí)分享Postgres的基礎(chǔ)知識(shí)和實(shí)踐內(nèi)幕。


學(xué)習(xí)內(nèi)容:(詳見目錄)

1、深入理解PostgreSQL數(shù)據(jù)庫之Support event trigger for logoff


學(xué)習(xí)時(shí)間:

2024年05月10日 23:32:16


學(xué)習(xí)產(chǎn)出:

1、PostgreSQL數(shù)據(jù)庫基礎(chǔ)知識(shí)回顧 1個(gè)
2、CSDN 技術(shù)博客 1篇
3、PostgreSQL數(shù)據(jù)庫內(nèi)核深入學(xué)習(xí)


注:下面我們所有的學(xué)習(xí)環(huán)境是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>

功能使用背景說明

前段時(shí)間PostgreSQL合入了Add support event triggers on authenticated login功能,可以看一下本人之前的博客:

  • PostgreSQL的學(xué)習(xí)心得和知識(shí)總結(jié)(一百三十六)|深入理解PostgreSQL數(shù)據(jù)庫之Add support event triggers on authenticated login,點(diǎn)擊前往

于是我跟建平?jīng)Q定實(shí)現(xiàn)一版 logoff 的事件觸發(fā)器,不過因?yàn)榭紤]的不是那么周全 外加社區(qū)的態(tài)度比較冷淡,該patch屬于放棄項(xiàng)。

在這里插入圖片描述

接下來本著開源分享的目的,我給大家詳細(xì)介紹一下其使用和實(shí)現(xiàn)原理。對(duì)此感興趣的小伙伴可以自行查看郵件列表:

  • Support event trigger for logoff,點(diǎn)擊前往

使用案例,如下:

-- src/test/regress/expected/event_trigger_logoff.out-- Logoff event triggers
CREATE TABLE user_logoffs(id serial, who text);
GRANT SELECT ON user_logoffs TO public;
CREATE FUNCTION on_logoff_proc() RETURNS event_trigger AS $$
BEGININSERT INTO user_logoffs (who) VALUES (SESSION_USER);
END;
$$ LANGUAGE plpgsql;
CREATE EVENT TRIGGER on_logoff_trigger ON logoff EXECUTE FUNCTION on_logoff_proc();
ALTER EVENT TRIGGER on_logoff_trigger ENABLE ALWAYS;
\c
-- Is it enough to wait 100ms to let the logoff event trigger execute?
SELECT pg_sleep(0.1);pg_sleep 
----------(1 row)SELECT COUNT(*) FROM user_logoffs;count 
-------1
(1 row)\c
SELECT pg_sleep(0.1);pg_sleep 
----------(1 row)SELECT COUNT(*) FROM user_logoffs;count 
-------2
(1 row)-- Check dathaslogoffevt in system catalog
SELECT dathaslogoffevt FROM pg_database WHERE datname = :'DBNAME';dathaslogoffevt 
-----------------t
(1 row)-- Cleanup
DROP TABLE user_logoffs;
DROP EVENT TRIGGER on_logoff_trigger;
DROP FUNCTION on_logoff_proc();
\c

補(bǔ)丁實(shí)現(xiàn)原理分析

注:此次的 patch 在實(shí)現(xiàn)上和 login 事件觸發(fā)器非常類似,接下來 重點(diǎn)看一下核心邏輯即可。若有想了解更加詳細(xì)的內(nèi)容,請(qǐng)看本人之前的博客!

// src/backend/tcop/postgres.c/* ----------------------------------------------------------------* PostgresMain*	   postgres main loop -- all backends, interactive or otherwise loop here** dbname is the name of the database to connect to, username is the* PostgreSQL user name to be used for the session.** NB: Single user mode specific setup should go to PostgresSingleUserMain()* if reasonably possible.* ----------------------------------------------------------------*/
void
PostgresMain(const char *dbname, const char *username)
{.../* Fire any defined login event triggers, if appropriate */EventTriggerOnLogin();/** Register a callback to fire any defined logoff event triggers, if* appropriate.*/if (IsUnderPostmaster)before_shmem_exit(EventTriggerOnLogoff, 0);...
}

在這里插入圖片描述


在這里插入圖片描述

因?yàn)槭莑ogoff事件觸發(fā)器,所以這里選擇before_shmem_exit注冊(cè)EventTriggerOnLogoff函數(shù),其邏輯如下:

// src/backend/storage/ipc/ipc.c/* ----------------------------------------------------------------*		before_shmem_exit**		Register early callback to perform user-level cleanup,*		e.g. transaction abort, before we begin shutting down*		low-level subsystems.*		*		注冊(cè)早期回調(diào)以執(zhí)行用戶級(jí)清理,例如 在我們開始關(guān)閉低級(jí)子系統(tǒng)之前,事務(wù)中止。* ----------------------------------------------------------------*/
void
before_shmem_exit(pg_on_exit_callback function, Datum arg)
{if (before_shmem_exit_index >= MAX_ON_EXITS)ereport(FATAL,(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),errmsg_internal("out of before_shmem_exit slots")));before_shmem_exit_list[before_shmem_exit_index].function = function;before_shmem_exit_list[before_shmem_exit_index].arg = arg;++before_shmem_exit_index;if (!atexit_callback_setup){atexit(atexit_callback);atexit_callback_setup = true;}
}

上述這些回調(diào)函數(shù),具體調(diào)用的地方 如下:

// src/backend/storage/ipc/ipc.c/* ------------------* Run all of the on_shmem_exit routines --- but don't actually exit.* This is used by the postmaster to re-initialize shared memory and* semaphores after a backend dies horribly.  As with proc_exit(), we* remove each callback from the list before calling it, to avoid* infinite loop in case of error.*  * 運(yùn)行所有 on_shmem_exit 例程 --- 但實(shí)際上并不退出* 后端嚴(yán)重死機(jī)后,postmaster 使用它來重新初始化共享內(nèi)存和信號(hào)量* 與 proc_exit() 一樣,我們?cè)谡{(diào)用每個(gè)回調(diào)之前從列表中刪除它,以避免出現(xiàn)錯(cuò)誤時(shí)無限循環(huán)* ------------------*/
void
shmem_exit(int code)
{shmem_exit_inprogress = true;/** Call before_shmem_exit callbacks.** These should be things that need most of the system to still be up and* working, such as cleanup of temp relations, which requires catalog* access; or things that need to be completed because later cleanup steps* depend on them, such as releasing lwlocks.*/elog(DEBUG3, "shmem_exit(%d): %d before_shmem_exit callbacks to make",code, before_shmem_exit_index);while (--before_shmem_exit_index >= 0)before_shmem_exit_list[before_shmem_exit_index].function(code,before_shmem_exit_list[before_shmem_exit_index].arg);before_shmem_exit_index = 0;...
}

最后再看一下EventTriggerOnLogoff函數(shù)的實(shí)現(xiàn),如下(該函數(shù)實(shí)現(xiàn)上類似于函數(shù)EventTriggerOnLogin):

// src/backend/commands/event_trigger.c/** Fire logoff event triggers if any are present.  The dathaslogoffevt* pg_database flag is left unchanged when an event trigger is dropped to avoid* complicating the codepath in the case of multiple event triggers.  This* function will instead unset the flag if no trigger is defined.*/
void
EventTriggerOnLogoff(int code, Datum arg)
{List	   *runlist;EventTriggerData trigdata;/** See EventTriggerDDLCommandStart for a discussion about why event* triggers are disabled in single user mode or via a GUC.  We also need a* database connection (some background workers don't have it).*/if (!IsUnderPostmaster || !event_triggers ||!OidIsValid(MyDatabaseId) || !MyDatabaseHasLogoffEventTriggers)return;StartTransactionCommand();runlist = EventTriggerCommonSetup(NULL,EVT_Logoff, "logoff",&trigdata, false);if (runlist != NIL){/** Event trigger execution may require an active snapshot.*/PushActiveSnapshot(GetTransactionSnapshot());/* Run the triggers. */EventTriggerInvoke(runlist, &trigdata);/* Cleanup. */list_free(runlist);PopActiveSnapshot();}/** There is no active logoff event trigger, but our* pg_database.dathaslogoffevt is set. Try to unset this flag.  We use the* lock to prevent concurrent SetDatabaseHasLogoffEventTriggers(), but we* don't want to hang the connection waiting on the lock.  Thus, we are* just trying to acquire the lock conditionally.*/else if (ConditionalLockSharedObject(DatabaseRelationId, MyDatabaseId,0, AccessExclusiveLock)){/** The lock is held.  Now we need to recheck that logoff event triggers* list is still empty.  Once the list is empty, we know that even if* there is a backend which concurrently inserts/enables a logoff event* trigger, it will update pg_database.dathaslogoffevt *afterwards*.*/runlist = EventTriggerCommonSetup(NULL,EVT_Logoff, "logoff",&trigdata, true);if (runlist == NIL){Relation	pg_db = table_open(DatabaseRelationId, RowExclusiveLock);HeapTuple	tuple;Form_pg_database db;ScanKeyData key[1];SysScanDesc scan;/** Get the pg_database tuple to scribble on.  Note that this does* not directly rely on the syscache to avoid issues with* flattened toast values for the in-place update.*/ScanKeyInit(&key[0],Anum_pg_database_oid,BTEqualStrategyNumber, F_OIDEQ,ObjectIdGetDatum(MyDatabaseId));scan = systable_beginscan(pg_db, DatabaseOidIndexId, true,NULL, 1, key);tuple = systable_getnext(scan);tuple = heap_copytuple(tuple);systable_endscan(scan);if (!HeapTupleIsValid(tuple))elog(ERROR, "could not find tuple for database %u", MyDatabaseId);db = (Form_pg_database) GETSTRUCT(tuple);if (db->dathaslogoffevt){db->dathaslogoffevt = false;/** Do an "in place" update of the pg_database tuple.  Doing* this instead of regular updates serves two purposes. First,* that avoids possible waiting on the row-level lock. Second,* that avoids dealing with TOAST.** It's known that changes made by heap_inplace_update() may* be lost due to concurrent normal updates.  However, we are* OK with that.  The subsequent connections will still have a* chance to set "dathaslogoffevt" to false.*/heap_inplace_update(pg_db, tuple);}table_close(pg_db, RowExclusiveLock);heap_freetuple(tuple);}else{list_free(runlist);}}CommitTransactionCommand();
}

在這里插入圖片描述

注:SetDatabaseHasLogoffEventTriggers有一處不同于SetDatabaseHasLoginEventTriggers,如下:

/** Set pg_database.dathaslogoffevt flag for current database indicating that* current database has on logoff event triggers.*/
void
SetDatabaseHasLogoffEventTriggers(void)
{/* Set dathaslogoffevt flag in pg_database */Form_pg_database db;Relation	pg_db = table_open(DatabaseRelationId, RowExclusiveLock);HeapTuple	tuple;/** Use shared lock to prevent a conflict with EventTriggerOnLogoff() trying* to reset pg_database.dathaslogoffevt flag.  Note, this lock doesn't* effectively blocks database or other objection.  It's just custom lock* tag used to prevent multiple backends changing* pg_database.dathaslogoffevt flag.*/LockSharedObject(DatabaseRelationId, MyDatabaseId, 0, AccessExclusiveLock);tuple = SearchSysCacheCopy1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));if (!HeapTupleIsValid(tuple))elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);db = (Form_pg_database) GETSTRUCT(tuple);if (!db->dathaslogoffevt){db->dathaslogoffevt = true;CatalogTupleUpdate(pg_db, &tuple->t_self, tuple);CommandCounterIncrement();/* take effect for the current session */MyDatabaseHasLogoffEventTriggers = true; /* ----- here ----- */}table_close(pg_db, RowExclusiveLock);heap_freetuple(tuple);
}
http://www.risenshineclean.com/news/57205.html

相關(guān)文章:

  • 開發(fā)什么網(wǎng)站好seo名詞解釋
  • 企業(yè)管理研究生學(xué)校排名seo引擎優(yōu)化怎么做
  • 一個(gè)人做網(wǎng)站原型網(wǎng)絡(luò)推廣團(tuán)隊(duì)哪家好
  • 上海浦東新區(qū)建設(shè)和交通委員會(huì)網(wǎng)站網(wǎng)絡(luò)熱詞作文
  • 那個(gè)網(wǎng)站做境外自由行便宜電商營銷推廣方案
  • 怎么做有趣的視頻網(wǎng)站軟文范例200字
  • 做簡歷的網(wǎng)站有抖音seo關(guān)鍵詞排名技術(shù)
  • 網(wǎng)站建設(shè)與制作教程百度競價(jià)點(diǎn)擊價(jià)格
  • 婚慶公司網(wǎng)站搭建免費(fèi)com域名申請(qǐng)注冊(cè)
  • 公司網(wǎng)站要怎么做正規(guī)電商培訓(xùn)班
  • 黑龍江電商網(wǎng)站建設(shè)廣州seo工程師
  • 杭州濱江網(wǎng)站建設(shè)公司整合營銷是什么
  • 河南手機(jī)網(wǎng)站建設(shè)公司哪家好seo網(wǎng)站關(guān)鍵詞排名軟件
  • 月嫂云商城網(wǎng)站建設(shè)百度廣告聯(lián)盟下載
  • 揚(yáng)州市江都區(qū)城鄉(xiāng)建設(shè)局網(wǎng)站愛站網(wǎng)關(guān)鍵詞排名
  • 中英版網(wǎng)站系統(tǒng)企業(yè)網(wǎng)絡(luò)推廣計(jì)劃書
  • 上海期貨配資網(wǎng)站開發(fā)上google必須翻墻嗎
  • 服務(wù)網(wǎng)絡(luò)營銷的含義太原seo推廣
  • 如何做跨境電商新手入門教程seo排名如何
  • 外包客服公司好做嗎首頁排名seo
  • 珠海市網(wǎng)站開發(fā)公司seo競價(jià)
  • 怎么做火短視頻網(wǎng)站seo門戶網(wǎng)價(jià)格是多少錢
  • 一個(gè)ip地址上可以做幾個(gè)網(wǎng)站今日新聞聯(lián)播
  • 做網(wǎng)站用什么語言要做網(wǎng)絡(luò)推廣
  • 海珠區(qū)有沒有專門做網(wǎng)站的地方全球最大的中文搜索引擎
  • 專業(yè)網(wǎng)站建設(shè) 公司哪家好杭州網(wǎng)站推廣與優(yōu)化
  • 網(wǎng)站推廣中應(yīng)注意哪些事項(xiàng)泉州seo技術(shù)
  • 做網(wǎng)站需要買seo中國是什么
  • 江蘇網(wǎng)站開發(fā)輿情分析網(wǎng)站免費(fèi)
  • 偷拍網(wǎng)站做色盲測試圖第六版