記錄一個oracle資料庫違反唯一性約束的問題
今天在觸發一個業務場景的時候,發現發出的報文無法入庫,檢視日誌發現當資料插入表時,報了違反唯一性約束的問題,但是明明之前操作是沒有問題的,追溯兩次執行過程中的變化,發現有人手動給那張表insert了200多萬條資料,除此之外沒有任何變化,在網上看了下相關問題的解決,才知道sequence的主鍵生成策略,當手動insert的時候不會更新序列,所以會有這樣的報錯, 解決方法有2:
- 手動更新序列
- 刪除手動插入的資料
解決問題的同時,也趁此機會了解一下主鍵生成策略有哪些:
- Assigned
Assigned方式由使用者生成主鍵值,並且要在save()之前指定否則會丟擲異常
特點:主鍵的生成值完全由使用者決定,與底層資料庫無關。使用者需要維護主鍵值,在呼叫session.save()之前要指定主鍵值。
- Hilo
Hilo使用高低位演算法生成主鍵,高低位演算法使用一個高位值和一個低位值,然後把演算法得到的兩個值拼接起來作為資料庫中的唯一主鍵。Hilo方式需要額外的資料庫表和欄位提供高位值來源。預設情況下使用的表是hibernate_unique_key,預設欄位叫作next_hi。next_hi必須有一條記錄否則會出現錯誤。
特點:需要額外的資料庫表的支援,能保證同一個資料庫中主鍵的唯一性,但不能保證多個數據庫之間主鍵的唯一性。Hilo主鍵生成方式由Hibernate 維護,所以Hilo方式與底層資料庫無關,但不應該手動修改hi/lo演算法使用的表的值,否則會引起主鍵重複的異常。
- Increment
Increment方式對主鍵值採取自動增長的方式生成新的主鍵值,但要求底層資料庫的主鍵型別為long,int等數值型。主鍵按數值順序遞增,增量為1。
特點:由Hibernate本身維護,適用於所有的資料庫,不適合多程序併發更新資料庫,適合單一程序訪問資料庫。不能用於群集環境。
- Identity
Identity方式根據底層資料庫,來支援自動增長,不同的資料庫用不同的主鍵增長方式。
特點:與底層資料庫有關,要求資料庫支援Identity,如MySQl中是auto_increment, SQL Server 中是Identity,支援的資料庫有MySql、SQL Server、DB2、Sybase和HypersonicSQL。 Identity無需Hibernate和使用者的干涉,使用較為方便,但不便於在不同的資料庫之間移植程式。
- Sequence
Sequence需要底層資料庫支援Sequence方式,例如Oracle資料庫等
特點:需要底層資料庫的支援序列,支援序列的資料庫有DB2、PostgreSql、Oracle、SAPDb等在不同資料庫之間移植程式,特別從支援序列的資料庫移植到不支援序列的資料庫需要修改配置檔案。
- Native
Native主鍵生成方式會根據不同的底層資料庫自動選擇Identity、Sequence、Hilo主鍵生成方式
特點:根據不同的底層資料庫採用不同的主鍵生成方式。由於Hibernate會根據底層資料庫採用不同的對映方式,因此便於程式移植,專案中如果用到多個數據庫時,可以使用這種方式。
- UUID
UUID使用128位UUID演算法生成主鍵,能夠保證網路環境下的主鍵唯一性,也就能夠保證在不同資料庫及不同伺服器下主鍵的唯一性。
特點:能夠保證資料庫中的主鍵唯一性,生成的主鍵佔用比較多的存貯空間
- Foreign GUID
Foreign用於一對一關係中。GUID主鍵生成方式使用了一種特殊演算法,保證生成主鍵的唯一性,支援SQL Server和MySQL
相關介紹來自百度百科。