網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
我們?cè)诤芏嗟胤綉?yīng)該都聽(tīng)到過(guò)長(zhǎng)事務(wù)的危害,比方說(shuō)長(zhǎng)事務(wù)會(huì)導(dǎo)致表膨脹之類(lèi)的。那么在PostgreSQL中什么才算是長(zhǎng)事務(wù)呢?
首先,在PostgreSQL的官方文檔中并沒(méi)有所謂“長(zhǎng)事務(wù)”這一定義,似乎大家約定俗稱(chēng)的把一個(gè)執(zhí)行了很長(zhǎng)卻沒(méi)有提交的事務(wù)認(rèn)為是“長(zhǎng)事務(wù)”了,而在不同的數(shù)據(jù)庫(kù)中關(guān)于長(zhǎng)事務(wù)的定義往往也不盡相同,那么在PostgreSQL中什么是長(zhǎng)事務(wù)呢?
打個(gè)比方,如下所示,我在一個(gè)會(huì)話(huà)中通過(guò)begin開(kāi)啟一個(gè)事務(wù),然后執(zhí)行了個(gè)簡(jiǎn)單的查詢(xún)語(yǔ)句后遲遲不提交,這算不算長(zhǎng)事務(wù)呢?
bill=# begin;
BEGIN
bill=*# select 1;
??column?
----------
? ? ? ? 1
(1 row)bill=*#
為了搞清楚這個(gè)問(wèn)題,我們不妨想想,為什么我們會(huì)提到長(zhǎng)事務(wù)呢。這是因?yàn)閜g中的長(zhǎng)事務(wù)會(huì)影響表中垃圾回收,會(huì)導(dǎo)致表的年齡增長(zhǎng)無(wú)法freeze。而我們上面這個(gè)會(huì)話(huà)開(kāi)啟的事務(wù)會(huì)有影響嗎?實(shí)際上并不會(huì),我們可以通過(guò)pg_stat_activity視圖觀(guān)察:
bill=# select * from pg_stat_activity where pid = 26192;
-[ RECORD 1 ]----+------------------------------
datid ? ? ? ? ? ?| 16385
datname ? ? ? ? ?| bill
pid ? ? ? ? ? ? ?| 26192
leader_pid ? ? ? |
usesysid ? ? ? ? | 16384
usename ? ? ? ? ?| bill
application_name | psql
client_addr ? ? ?|
client_hostname ?|
client_port ? ? ?| -1
backend_start ? ?| 2022-03-02 11:49:49.433165+08
xact_start ? ? ? | 2022-03-02 14:34:04.494416+08
query_start ? ? ?| 2022-03-02 14:34:06.946754+08
state_change ? ? | 2022-03-02 14:34:06.947207+08
wait_event_type ?| Client
wait_event ? ? ? | ClientRead
state ? ? ? ? ? ?| idle in transaction
backend_xid ? ? ?|
backend_xmin ? ? |
query ? ? ? ? ? ?| select 1;
backend_type ? ? | client backend
之所以會(huì)導(dǎo)致表膨脹之類(lèi)的問(wèn)題,主要是在于backend_xid和backend_xmin兩個(gè)字段,而上面的事務(wù)這兩個(gè)字段均是空的。
/* ----------
* LocalPgBackendStatus
*
* When we build the backend status array, we use LocalPgBackendStatus to be
* able to add new values to the struct when needed without adding new fields
* to the shared memory. It contains the backend status as a first member.
* ----------
*/
typedef struct LocalPgBackendStatus
{
/*
* Local version of the backend status entry.
*/
PgBackendStatus backendStatus;
/*
* The xid of the current transaction if available, InvalidTransactionId
* if not.
*/
TransactionId backend_xid;
/*
* The xmin of the current session if available, InvalidTransactionId if
* not.
*/
TransactionId backend_xmin;
} LocalPgBackendStatus;
backend_xid表示已申請(qǐng)事務(wù)號(hào)的事務(wù),例如有增刪改,DLL等操作的事務(wù)。backend_xid從申請(qǐng)事務(wù)號(hào)開(kāi)始持續(xù)到事務(wù)結(jié)束。
backend_xmin表示SQL執(zhí)行時(shí)的snapshot,即可見(jiàn)的最大已提交事務(wù)。
而表膨脹的原因是什么呢?當(dāng)數(shù)據(jù)庫(kù)中存在未結(jié)束的SQL語(yǔ)句或者未結(jié)束的持有事務(wù)ID的事務(wù),在此事務(wù)過(guò)程中,或在此SQL執(zhí)行時(shí)間范圍內(nèi)產(chǎn)生垃圾的話(huà),這些垃圾無(wú)法回收,導(dǎo)致數(shù)據(jù)庫(kù)膨脹。
也就是判斷當(dāng)前數(shù)據(jù)庫(kù)中backend_xid和backend_xmin最小的值,凡是超過(guò)這個(gè)最小值的事務(wù)產(chǎn)生的垃圾都不能回收。
因此,我們?nèi)绻胍O(jiān)控長(zhǎng)事務(wù)該怎么寫(xiě)呢?以超過(guò)1小時(shí)的長(zhǎng)事務(wù)為例:
select count(*) from pg_stat_activity where state <> 'idle'
and (backend_xid is not null or backend_xmin is not null)
and now()-xact_start > interval '3600 sec'::interval;
所以,對(duì)于事務(wù)而言,只有當(dāng)執(zhí)行了一些DML或者DDL操作后才能算是我們通常說(shuō)的長(zhǎng)事務(wù)。否則只能算是我們常說(shuō)的長(zhǎng)連接,當(dāng)然長(zhǎng)連接也有很多弊端,例如占用內(nèi)存、cpu等資源。
在實(shí)際應(yīng)用中,我們應(yīng)當(dāng)做好對(duì)長(zhǎng)事務(wù)的監(jiān)控,并盡可能的避免其發(fā)生。例如一些批量的操作可能會(huì)比較容易導(dǎo)致長(zhǎng)事務(wù),我們可以盡量將其安排在業(yè)務(wù)低峰期執(zhí)行,同時(shí),如果我們的應(yīng)用中關(guān)閉了自動(dòng)提交,也要在執(zhí)行完之后加上提交。
原文鏈接:https://foucus.blog.csdn.net/article/details/123230865
相關(guān)推薦
- 2022-11-15 python管理包路徑之pycharm自動(dòng)解決包路徑注冊(cè)_python
- 2022-04-19 React?組件權(quán)限控制的實(shí)現(xiàn)_React
- 2022-08-22 C++示例詳解Prim算法與優(yōu)先隊(duì)列_C 語(yǔ)言
- 2022-09-16 Kubernetes教程之Windows?HostProcess?運(yùn)行容器化負(fù)載_云其它
- 2022-12-28 React組件通信實(shí)現(xiàn)流程詳解_React
- 2022-01-19 解決form表單reset()報(bào)錯(cuò),$(...)[0].reset is not a functio
- 2022-10-03 Golang?Http請(qǐng)求返回結(jié)果處理_Golang
- 2021-11-21 ASP.NET?Core應(yīng)用JWT進(jìn)行用戶(hù)認(rèn)證及Token的刷新方案_實(shí)用技巧
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支