UAT環(huán)境PostgreSQL ON CONFLICT DO UPDATE報(bào)錯(cuò)問題及解決
背景
為應(yīng)對(duì)最后上線測(cè)試,在 UAT 環(huán)境進(jìn)行一次總量3000萬的數(shù)據(jù)集成,數(shù)據(jù)分為4種DataSorce.
在執(zhí)行到第三種DataSource時(shí),集成失敗。并收到告警郵件,提醒如下報(bào)錯(cuò),講這個(gè)報(bào)錯(cuò)前。
就得下說一下當(dāng)前數(shù)據(jù)集成方案:
### Cause: PSQLException: ERROR: ON CONFLICT DO UPDATE command cannot affect row a second time
建議:Ensure that no rows proposed for insertion within the same command have duplicate constrained values.
; ERROR: ON CONFLICT DO UPDATE command cannot affect row a second time
建議:Ensure that no rows proposed for insertion within the same command have duplicate constrained values.; nested exception is org.postgresql.util.PSQLException: ERROR: ON CONFLICT DO UPDATE command cannot affect row a second time
建議:Ensure that no rows proposed for insertion within the same command have duplicate constrained values., 2025-06-18 14:31:12.729, 2025-06-18 15:50:03.329, 4213015, 20250618143057241, 1750227637384308, 2, 2025-06-18 17:10:06.947774, 2025-06-19 09:25:29.999212, 0, 2025-06-19 10:20:39.607914, 2025-06-19 10:36:15.499851
<== Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4f49b57a]?
當(dāng)前集成方案 (演示)
INSERT INTO master_order (order_id, order_info, product_info, geo_info)
SELECT A.order_id,
A.order_id,
P.product_info,
G.geo_info
FROM
transaction_table
A LEFT JOIN product_table P ON A.product_no = P.product_no
LEFT JOIN geo_table G ON A.country_code = G.country_code
WHERE
version_number = '001' ON CONFLICT (order_id) DO
UPDATE
SET order_info = excluded.order_info,
product_info = excluded.product_info,
geo_info = geo_info.geo_info這里使用的是 ON CONFLICT DO UPDATE 函數(shù). 又稱 UPSERT 方式,即通過主鍵判斷:當(dāng)記錄不存在 執(zhí)行插入,否則進(jìn)行更新!
建議:
- 在做大數(shù)據(jù)量數(shù)據(jù)處理時(shí).
- 要優(yōu)先使用UPSERT方式,避免使用先刪除再插入方式。
- 先刪除在插入處理大數(shù)據(jù)量時(shí)性能不好,造成大量索引重建。
- 數(shù)據(jù)頁分 裂,大量空間碎片等問題。
UPSERT 使用限制
1.CONFLICT(字段1,字段2) 必須為唯一主鍵
upsert 使用的字段必須要主鍵索引(PK)。必須主鍵PK. 二級(jí)索引都不行.
2.更新的數(shù)據(jù)源主鍵不允許重復(fù)
什么意思呢?
由于master_order 中 order_id 是唯一主鍵。
就必須要求數(shù)據(jù)源SQL的結(jié)果中不允許有重復(fù)的 KEY(order_id).否則就報(bào)錯(cuò). PostgreSQL不會(huì)主動(dòng)去處理這種報(bào)錯(cuò), 需要用戶自己來保障。
屬于用戶責(zé)任:
// 這個(gè)結(jié)果必須要唯一,一個(gè)order_id 只能有一條數(shù)據(jù) SELECT A.order_id, A.order_id, P.product_info, G.geo_info FROM transaction_table A LEFT JOIN product_table P ON A.product_no = P.product_no LEFT JOIN geo_table G ON A.country_code = G.country_code WHERE version_number = '001'
問題分析
第一條!滿足.
第二條!系統(tǒng)開發(fā)文檔明明記錄著 transaction_table 表 order_id 主鍵,product_table 表 product_no 是主鍵, geo_table 表 country_code 主鍵。所以應(yīng)該也沒問題??!那為啥還報(bào)錯(cuò)?馬上給Pgsql 提 issue,發(fā)現(xiàn)bug 了......
最后檢查發(fā)現(xiàn),不知道哪位勇猛的好戰(zhàn)友將 product_table 表中 product_no 主鍵去掉了。然后插入了兩條一模一樣的產(chǎn)品編號(hào)數(shù)據(jù).在關(guān)聯(lián)查詢中就導(dǎo)致了一個(gè) order_id 對(duì)應(yīng)了多條訂單數(shù)據(jù)。
解決:趕緊刪除冗余數(shù)據(jù).重新為product_table 表設(shè)置 product_no 主鍵索引.手動(dòng)重啟集成。危機(jī)解除!
。??上Я?,只是UAT ,應(yīng)該把生產(chǎn)環(huán)境都改咯才是好!
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
PostgreSQL查詢修改max_connections(最大連接數(shù))及其它配置詳解
postgresql數(shù)據(jù)庫(kù)最大連接數(shù)是系統(tǒng)允許的最大連接數(shù),當(dāng)數(shù)據(jù)庫(kù)并發(fā)用戶超過該連接數(shù)后,會(huì)導(dǎo)致新連接無法建立或者連接超時(shí),這篇文章主要給大家介紹了關(guān)于PostgreSQL查詢修改max_connections(最大連接數(shù))及其它配置的相關(guān)資料,需要的朋友可以參考下2024-01-01
PostgreSQL的日期時(shí)間差DATEDIFF實(shí)例詳解
PostgreSQL是一款簡(jiǎn)介而又性能強(qiáng)大的數(shù)據(jù)庫(kù)應(yīng)用程序,其在日期時(shí)間數(shù)據(jù)方面所支持的功能也都非常給力,下面這篇文章主要給大家介紹了關(guān)于PostgreSQL的日期時(shí)間差DATEDIFF的相關(guān)資料,需要的朋友可以參考下2023-04-04
psql除法保留小數(shù),實(shí)現(xiàn)向上取整和向下取整操作
這篇文章主要介紹了psql除法保留小數(shù),實(shí)現(xiàn)向上取整和向下取整操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01
PostgreSQL數(shù)據(jù)庫(kù)實(shí)現(xiàn)公網(wǎng)遠(yuǎn)程連接的操作步驟
PostgreSQL是一個(gè)功能非常強(qiáng)大的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(RDBMS),本文呢將簡(jiǎn)單幾步通過cpolar 內(nèi)網(wǎng)穿透工具即可現(xiàn)實(shí)本地postgreSQL 遠(yuǎn)程訪問,需要的朋友可以參考下2023-09-09
PostgreSQL中的template0和template1庫(kù)使用實(shí)戰(zhàn)
這篇文章主要介紹了PostgreSQL中的template0和template1庫(kù)使用實(shí)戰(zhàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01
PGSQL查詢最近N天的數(shù)據(jù)及SQL語句實(shí)現(xiàn)替換字段內(nèi)容
PostgreSQL提供了WITH語句,允許你構(gòu)造用于查詢的輔助語句,下面這篇文章主要給大家介紹了關(guān)于PGSQL查詢最近N天的數(shù)據(jù)及SQL語句實(shí)現(xiàn)替換字段內(nèi)容的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03

