因為一條sql 我開始懷疑自己了
theme: channing-cyan
「回顧2022,展望2023,我正在參與2022年終總結徵文大賽活動」
故事是這樣開始的
在一個月黑風高的夜晚
現場報過來,本該打到新服務的流量,又走到了老服務,老服務的功能不健全,很可能會讓現場的使用者不能支付。 需要說明一點的是,任何一個從老服務改造到新服務的時候,都不是完全把流量切過去,都需要經過一點時間去驗證。
比如我們按照地理位置去切,將北京的部分車場(是的,我們是做停車服務的),切到新服務,其他城市的車場在老服務
我們採用最簡單的辦法,就是靠一個欄位type去控制(0和1)
看似簡單,但是事怪就怪在這個欄位上,這個控制欄位是屬於後來加到資料庫欄位的,而且沒有對外去配置,都是通過運維手動去資料庫配置的,且資料庫欄位預設值設定為1。
可總有幾個車場時不時的從0就變成了1。。眾所周知,一個新的欄位不在mybatis xml和pojo出現,那麼就不會有操作改掉
翻遍所有的服務,關乎這個表的都是update操作,update操作因為沒有這個欄位時打死也不會改這個type的
冷靜下來想想,資料庫預設欄位為1,然後0都會變成1。沒有1變成0的,可以肯定的是,先刪除,又新增了,否則沒有別的解釋
經過一番查驗,找到這樣一堆程式碼(虛擬碼)
``xml
replace INTO
A` (
park_id,
xxxx,
xxxx
)
SELECT
park_id,
xxxx,
xxxx
FROM
B
where b.park_id = #{parkId}
```
看到這裡,心裡嘿嘿一笑,破案了。。。。。
replace INTO
是的,就是replace INTO搞得鬼,大家都知道,replace INTO和insert into的區別
1、replace into 首先嚐試插入資料到表中, 如果發現表中已經有此行資料(根據主鍵或者唯一索引判斷)則先刪除此行資料,然後插入新的資料。
2、如果表中無此資料,則插入新資料。
這就正好驗證了上面的猜想,只有刪除再新增,才會讓type跟隨資料庫的預設值走
講到這裡不妨我們多瞭解一點這個,有人可能會問,replace是不是取代了insert和delete,畢竟是幹了兩件事
MySql手冊關於replace into的演算法:Mysql手冊
```js MySQL uses the following algorithm for REPLACE (and LOAD DATA ... REPLACE):
Try to insert the new row into the table
While the insertion fails because a duplicate-key error occurs for a primary key or unique index:
Delete from the table the conflicting row that has the duplicate key value
Try again to insert the new row into the table
MySQL對REPLACE(和LOAD DATA…REPLACE)使用以下演算法:
嘗試將新行插入表中
當由於主鍵或唯一索引出現重複鍵錯誤而導致插入失敗時:
從表中刪除具有重複鍵值的衝突行
再次嘗試將新行插入表中 ```
先插入, 出錯了再執行delete加insert. 如果自己用程式來做, 個人認為效率會低很多,另外這樣寫真的很搞人
這裡推薦使用INSERT...ON DUPLICATE KEY UPDATE, 感覺很靠譜. replace的副作用:
-
replace每次要重新分配自增id;
-
replace中執行delete時, 在有外來鍵的情況下會很麻煩;
-
如果delete時定義的有觸發器, 則會被執行;
- 副作用也會被傳播到replica slave
總結
開發當中難免遇到奇奇怪怪的各種問題,有問題莫慌,冷靜分析,你認為的不可能事件、你認為的計算機會發生錯誤,其實都是自己沒有去完全理解到位,跟蹤到位!!!
最後祝大家2023,少寫bug,少加班,多漲薪
- 因為一條sql 我開始懷疑自己了
- 建議你去String.valueOf()
- 這五年,經歷了什麼!
- 短短1個小時,讓公司損失近3萬
- 辭職申請書都寫好了
- 為什麼SpringBoot什麼都不需要配置就可以執行起來(每天一題,一起進大廠)
- 今天面了一個人,問了個JavaConfig(每天一題,一起進大廠)
- 看完這篇文章才知道什麼是java反射(每天一題,一起進大廠)
- 新來的同事問我 怎麼沒有mapper.xml檔案
- 新來的同事問我where 1=1 是什麼意思
- 一文搞懂Nginx代理
- Spring Security 如何將使用者資料存入資料庫?(Spring Security專題)
- 同事教我SpringBoot解決跨域
- 同事告訴我應該這樣判空
- Spring Security專欄(自定義Security中的加密)
- Spring Security專欄(如何利用Spring Security搭建使用者體系)
- 介面統一返回(拿去即用)