pgsql数据库默认配置事务类型_postgreSql最佳配置详解(connection 申请、回收策略)...
一、引子
合理配置一個(gè)應(yīng)用的數(shù)據(jù)庫參數(shù),使其運(yùn)行良好,這很重要。本文以某務(wù)中臺(tái)的生產(chǎn)環(huán)境為例,從Apollo上拔下來一套配置,分析是否合理。
二、MybatisPlus配置
由于我們使用Apollo配置參數(shù),所以分兩部分:1.個(gè)體配置 2.全局配置
2.1 mybatisplus個(gè)體配置
mybatis-plus.mapper-locations = classpath*:/mapper/*Mapper.xml? mapper文件地址匹配
mybatis-plus.type-aliases-package =xx.po 映射的實(shí)體包路徑,
mybatis-plus.tenant-config.ignoretable = table1,table2
mybatis-plus.auth-config = []
mybatis-plus.global-config.sql-parser-cache = true 緩存sql解析
2.2 mybatis-plus全局配置
mybatis-plus.mapper-locations = classpath:/mapper/*Mapper.xml? mapper文件地址匹配
mybatis-plus.configuration.map-underscore-to-camel-case = true??? 下劃線轉(zhuǎn)駝峰
mybatis-plus.global-config.logic-delete-value = true? 邏輯已刪除值
mybatis-plus.global-config.logic-not-delete-value = false? 邏輯未刪除值
mybatis-plus.max-query-records-size = 10000
三、Datasource配置
3.1 dataSource個(gè)體配置
=========數(shù)據(jù)庫配置=========
spring.datasource.connectionProperties = druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄5秒
spring.datasource.type = com.alibaba.druid.pool.DruidDataSource 使用德魯伊連接池
spring.datasource.driver-class-name = org.postgresql.Driver 驅(qū)動(dòng)類名
spring.datasource.url = xx? 數(shù)據(jù)庫連接url
spring.datasource.username = ${dbUserName} 用戶名
spring.datasource.password = ${dbPassword} 密碼
spring.datasource.minIdle = 5 最小空閑連接數(shù) 5
spring.datasource.initialSize = 5 初始連接數(shù) 5
spring.datasource.maxActive = 100 最大連接數(shù)
spring.datasource.maxWait = 60000 獲取連接等待超時(shí)的時(shí)間 60s=1分鐘
spring.datasource.filters = stat,wall 監(jiān)控統(tǒng)計(jì)攔截,用于監(jiān)控界面sql統(tǒng)計(jì)
spring.datasource.poolPreparedStatements = false 是否啟用緩存PreparedStatements
spring.datasource.maxPoolPreparedStatementPerConnectionSize = 20 指定每個(gè)連接上preStatement緩存數(shù)---》未生效!!!
=========健康檢查=========
spring.datasource.validationQuery = SELECT 1 連接池的健康檢查SQL
spring.datasource.testOnBorrow = false 申請(qǐng)連接時(shí)執(zhí)行validationQuery檢測連接是否有效,做了這個(gè)配置會(huì)降低性能。
spring.datasource.testOnReturn = false 歸還連接時(shí)執(zhí)行validationQuery檢測連接是否有效,做了這個(gè)配置會(huì)降低性能
spring.datasource.testWhileIdle = true 建議配置為true,不影響性能,并且保證安全性。申請(qǐng)連接的時(shí)候檢測,如果空閑時(shí)間大于timeBetweenEvictionRunsMillis,執(zhí)行validationQuery檢測連接是否有效。
#每timeBetweenEvictionRunsMillis毫秒檢查一次連接池中空閑的連接,把空閑時(shí)間超過minEvictableIdleTimeMillis毫秒的連接斷開,直到連接池中的連接數(shù)到minIdle為止
spring.datasource.minEvictableIdleTimeMillis = 300000 最小可驅(qū)逐空閑時(shí)間,連接保持空閑而不被驅(qū)逐的最長時(shí)間,單位是毫秒 300s=5分鐘
spring.datasource.timeBetweenEvictionRunsMillis = 60000 間隔多久才進(jìn)行一次驅(qū)逐檢測,單位是毫秒 60s=1分鐘
=========連接超時(shí)=========
# 關(guān)閉abanded連接時(shí)輸出錯(cuò)誤日志,預(yù)生產(chǎn)/生產(chǎn)不建議開啟,對(duì)性能影響
spring.datasource.logAbandoned = false
# 是否清除已經(jīng)超過“removeAbandonedTimout”設(shè)置的無效連接。
spring.datasource.removeAbandoned = true
# 連接超過指定時(shí)間未關(guān)閉,就會(huì)被強(qiáng)行回收 180s=3分鐘
spring.datasource.removeAbandonedTimeoutMillis = 180000
四、源碼剖析
看完配置,大家心里還是懵逼對(duì)吧,參數(shù)如何生效,druid到底如何運(yùn)行?
下面,帶著問題,深入源碼,直接剖析druid如何申請(qǐng)連接、釋放連接、連接泄露檢查。
4.1.申請(qǐng)連接
最終跟進(jìn)到DruidDataSource的getConnectionDirect(long maxWaitMillis),獲取得到連接后,validationQuery有效性檢查,源碼如下:
1.testOnBorrow =true,先直接校驗(yàn),執(zhí)行validationQuery,失敗就關(guān)閉連接JdbcUtils.close(realConnection);
2.testWhileIdle=true,如果testOnBorrow =false, 測試空閑的連接,執(zhí)行validationQuery,失敗就關(guān)閉連接JdbcUtils.close(realConnection);
3.removeAbandoned=true,如果開啟了泄露回收:把連接添加進(jìn)Map activeConnections 。供泄露回收時(shí)使用。
分支1和2只會(huì)有一個(gè)執(zhí)行。
4.2.釋放連接
德魯伊連接池在獲取連接時(shí),會(huì)調(diào)用一次DruidDataSource的init()。方法中createAndStartDestroyThread()開啟了一個(gè)銷毀線程。
銷毀連接的線程包含了run(),如下:
在一個(gè)for空條件循環(huán)中,根據(jù)配置的timeBetweenEvictionRunsMillis連接檢測間隔時(shí)間,執(zhí)行一次DestroyTask.run()就休眠一次間隔時(shí)間。未設(shè)置默認(rèn)60s。(實(shí)際源碼中定義了60spublic static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = 60 * 1000L;,所以用戶未設(shè)置,默認(rèn)60s,上圖中else分支sleep1秒不會(huì)執(zhí)行到)
追蹤DestroyTask.run()如下:
2個(gè)步驟:
shrink()收縮校驗(yàn)
removeAbandoned()連接泄露移除
shrink()收縮校驗(yàn)
DruidDataSource內(nèi)部定義了DruidConnectionHolder[] 類型的3個(gè)數(shù)組:
1.connections:可用連接數(shù)組。申請(qǐng)連接就從這里數(shù)組隊(duì)尾拿連接。
2.evictConnections:待移除連接數(shù)組。
3.keepAliveConnections:待保活檢測數(shù)組。
塞進(jìn)數(shù)組
shrink()中計(jì)算出需要校驗(yàn)的數(shù)量checkCount,執(zhí)行收縮校驗(yàn)核心邏輯:
校驗(yàn)物理連接的超時(shí)時(shí)間phyTimoutMills:超時(shí)放入evictConnections中,等待移除。
空余時(shí)間大于minEvictableIdleTimeMillis(受保最小空閑時(shí)間),并且索引(poolingCount)小于checkCount的連接則放入evictConnections;
空余時(shí)間大于minEvictableIdleTimeMillis(受保最小空閑時(shí)間),并且索引大于checkCount的連接,假若空余時(shí)間大于maxEvictableIdleTimeMillis則放入evictConnections,否則放入keepAliveConnections中進(jìn)行keepAlive檢測。
如下圖:
數(shù)組處理
1.evictConnections:待移除連接數(shù)組。使用JdbcUtils.close()? 關(guān)閉連接。
2.keepAliveConnections:待保活檢測數(shù)組。根據(jù)配置的validationQuery查詢SQL執(zhí)行連接可用性校驗(yàn)。校驗(yàn)通過后再put(holder)塞進(jìn)connections可用連接數(shù)組。
4.3.泄露連接移除
如果開啟了removeAbandoned ,執(zhí)行removeAbandoned()。移除泄露連接邏輯如下:
實(shí)際上,就是對(duì)可能的連接泄露(打開連接后長時(shí)間不關(guān)閉)兜底。
1)遍歷活躍連接Map activeConnections。
2)跳過運(yùn)行中的連接,running定義:執(zhí)行SQL前賦值true ,執(zhí)行完后置false。---》問題1得到答案,不會(huì)暴力關(guān)閉執(zhí)行中的連接。
3)如果當(dāng)前連接已連接時(shí)間>=removeAbandonedTimeoutMillis ,直接從activeConnections map 中移除。
這里消耗性能主要兩步驟:
1.內(nèi)存中記錄+移除泄露連接
2.打印相關(guān)日志的IO---》logAbandoned=false 可關(guān)閉寫日志
spring 的druid 連接池一般不會(huì)造成泄露。如果出現(xiàn)連接泄露,應(yīng)該找到問題解決。---》問題2得到答案,目前關(guān)閉了寫日志,就剩下了第一點(diǎn)“內(nèi)存占用+過濾的性能”成本,要求不高的場景可以作為兜底方案使用。如果項(xiàng)目已穩(wěn)定,推薦關(guān)閉。
五.分析&總結(jié)
本節(jié)為我們根據(jù):申請(qǐng)、釋放連接相關(guān)的參數(shù)配置,剖析策略是否合理。
5.1 配置分析
spring.datasource.testOnBorrow = false 申請(qǐng)連接時(shí)執(zhí)行validationQuery檢測連接是否有效
spring.datasource.testOnReturn = false 歸還連接時(shí)執(zhí)行validationQuery檢測連接是否有效
spring.datasource.testWhileIdle = true testOnBorrow=false時(shí)才生效,申請(qǐng)連接的時(shí)候檢測,如果空閑時(shí)間大于timeBetweenEvictionRunsMillis,執(zhí)行validationQuery檢測連接是否有效。
spring.datasource.initialSize = 5 初始連接數(shù) 5
spring.datasource.maxActive = 100 最大連接數(shù)
spring.datasource.minIdle = 5 最小空閑連接數(shù) 5
timeBetweenEvictionRunsMillis= 60000 60s=1分鐘檢測一次
minEvictableIdleTimeMillis=300000 300s=5分鐘 最小空閑不移除時(shí)間
maxEvictableIdleTimeMillis 未設(shè)置最大空閑移除時(shí)間,默認(rèn)DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 60L * 7 = 7小時(shí)。
keepAlive: 未設(shè)置保活開關(guān),默認(rèn)false關(guān)閉。不執(zhí)行保活測試策略。
上述配置對(duì)應(yīng)的策略:
1.初始策略
初始5個(gè)連接,最多可開啟100個(gè)連接。
2.申請(qǐng)策略
申請(qǐng)連接的時(shí)候檢測,如果連接空閑時(shí)間大于1分鐘(檢測間隔時(shí)間),執(zhí)行validationQuery檢測連接是否有效。---》這里可確保我們空閑時(shí)間超過1分鐘的連接,校驗(yàn)后使用。
3.回收策略
每一分鐘執(zhí)行一次檢測,策略如下:
1.連接空閑小于5分鐘,不移除。
2.連接空閑大于5分鐘,保留”minIdle設(shè)置的5個(gè)idle連接”,可移除(總數(shù)-5)個(gè)連接。
3.連接空閑大于7小時(shí),可移除“minIdle設(shè)置的5個(gè)idle連接”。---》因?yàn)闆]有設(shè)置maxEvictableIdleTimeMillis ,默認(rèn)空閑7小時(shí)后才會(huì)移除。不過一共就5個(gè)倒也沒什么事。
4.連接空閑5分鐘~7小時(shí),由于沒開啟keepAlive保活開關(guān),無法對(duì)“minIdle設(shè)置的5個(gè)idle連接”保活測試。-->minIdle設(shè)置的5個(gè)idle連接,這段時(shí)間一直不回收,也不做保活測試,連接是否有效無法保證。
5.2總結(jié)
1.現(xiàn)有項(xiàng)
removeAbandoned=true 開啟連接泄露檢測,要求不高的場景可以作為兜底方案使用。如果項(xiàng)目已穩(wěn)定,推薦關(guān)閉。
2.可添加項(xiàng)
phyTimeoutMillis:看需要開啟。物理超時(shí)時(shí)間。不管空閑時(shí)間,超時(shí)直接移除。---》這個(gè)是終極兜底方案,可以確保超時(shí)強(qiáng)制移除。
maxEvictableIdleTimeMillis:建議開啟,實(shí)現(xiàn)精細(xì)化控制。
keepAlive: 建議開啟。可針對(duì)“minIdle設(shè)置的空閑連接”,進(jìn)行保活測試,從而提升連接的質(zhì)量。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的pgsql数据库默认配置事务类型_postgreSql最佳配置详解(connection 申请、回收策略)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 星推客是什么
- 下一篇: php弹幕技术轮询,PHP实现长轮询消息