使用sharding做分庫分表,使用jpa,發生的save不報錯,數據庫缺插不進去數據的問題

  先講講問題的誕生,我們項目起初沒有引進 sharding分庫,而是在項目上線前,才做的分庫分表。也就是之前的業務都寫好的,所以知道業務代碼沒有任何問題。

  然後引入 sharding 的相關的依賴以後,分庫分表的先關配置都做好,可以保證沒有任何的問題以後。

  當然了,sharding不支持一些sql,比如 distinct,比如 聚合函數需要起一個別名。這些問題都排查過了。

  問題出現在,跑 test 測試類的時候,發現程序也不報錯,但是數據庫裏邊沒有數據進去。奇怪就奇怪在 啓動項目,通過postmen 調用controller 的形式, 就能插進去數據。這足以說明數據庫沒問題。sharding配置沒問題,程序代碼也沒問題。

  定時任務裏邊調用 service ,也不行,就和 test 一樣,打印sql,發現沒有insert語句。這就很奇怪了,咋好好的跑測試類,就沒有 insert語句了呢?

 

# # 起初的毫無頭緒

  就覺得這個問題很神奇。缺沒有任何排查的思路,可能還是太年輕了。

 

# # 接下來看看我的解題思路

  我覺得雖然問題有可能不是通一個問題,但是解決問題的思路都相似,這就是經驗,這就是方法論。

  不報錯,只有數據庫插不進去數據的現象,卻沒有任何報錯信息。這怎麼辦?我相信,只拿着這個現象去搜,決絕有一大堆不想幹的帖子出來干擾你。

   我的搜索詞條是: 使用jpa,save無法插入數據庫數據數據。

  果然,有很多的帖子,但是都和我的不相關,因爲他們都是單純的環境沒部好,因爲我之前的 save沒問題,只是在使用sharding以後纔有問題。保存不進去值的問題,我看了網上幾乎所有的帖子,谷歌到了 2010年的帖子,都是在說 save不進去值的問題。 沒有一個是和我相關的答案。

  所以花了很多時間,幾乎看到想吐。很多就是問題描述不清楚。

 

# # 如此奇怪的現象,走投無路,我只能用排除法

 既然這個問題是引入 sharidng以後纔出現的,是不是sharding版本的問題?於是,我重新搭了環境,換成了高版本的 sharding 的依賴。之前的數據庫是 PG,我換成了mysql,發現,竟然沒問題,test的 save能保存進去數據。然後把項目的依賴也進行了升級。發現還是不好使。

  然後,還是用排除法,我又重新搭建了項目。在父工程下,創建了一個子項目,然後所有的依賴都用原來的。就是純淨的環境,最簡單的測試,一個實體類,因爲用的 JPA,所以只用一個 repository,然後 一層 service,一個測試類。就和原來的套路一樣,結果發現,test能插進去數據。

  問題又回到了詭異狀態,爲什麼項目就不能跑。重新搭建的就可以?還是一頭霧水。

 

# # 我把 save 改成了 saveAndFlush 

  於是開始報錯了,報一個沒有事務的錯誤:描述如下:

org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress

  你去搜這個問題,一定告訴你的是,讓你添加 @Transactional 註解。我明明加過了,啓動項目,調用controller就不報錯,跑測試類就出錯。

  因爲實在沒思路了,只能盯着報錯的去一層一層的看了。爲啥我啓動項目就可以,跑測試類就報錯呢?

  我找DBA幫忙看看,她也是看到 select語句,沒有任何 insert 語句。讓他幫我盯着事務看一看,沒有看到。

  這就奇怪了,我明明加了事務的, 卻報沒有事務的錯。錯肯定不會好端端的報出來的。在這種奇怪的情況下,我的直覺就是 事務的問題。究竟是怎麼產生的,我還是沒頭緒。一直覺得不是自己的錯。

 

# # 我開始排查事務管理器

 也查看了很多文章,事務相關的問題。這個思路是來源於 save保存不進去數據,這問題進行谷歌,很多人,都說事務回滾什麼的。根據我的情況,我排查覺得,是不是到了這裏,事務已經提交了,所以只有 select 沒有 insert。是不是事務提交了,可是又爲什麼會提交了呢?

  爲什麼回報沒有事務的錯誤呢? 然後看到文章,有查看事務管理器的,我就拿着報錯的項目,和不報錯的項目對比。發現事務管理器用的不相同。根據上邊的排除,不是依賴的錯誤,不是代碼的錯誤,不是數據庫的錯誤。差異看到的就只有這個事務管理器了。我就想着更換一下事務管理器,正確的項目用的是 jpa 的事務管理器,我出問題的是用的 dataSource 的事務管理器。springboot 默認注入的。

  於是就切換:具體情況我這篇文章

  切換以後,問題還真解決了。

 

# # 爲啥同樣的環境,用的卻不是同一個事務管理器呢

  我也查了文章:可以看看這篇文章:http://c.biancheng.net/view/4644.html

  我只引入了 jpa 的starter,但是卻沒有用 jpa 的事務管理器,這個還要在項目裏邊排查。看看究竟是怎麼回事。後續再更新出來。

 

# # 總結

   前幾天還遇到過一個奇怪的現象,就是控制檯報錯,不一定準。即使明明給你準確的一行,也不一定準,還是要單獨拿出來測試的。

  遇到問題,特別是奇怪的問題。都是要硬着頭皮解決的。重新搭環境,搞出來正確的,再去對比,有時候也是很好用的方案。

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章