自上個月某個功能改動上線以後,最近生產上連環出現了多個生產故障,故障基本描述如下:
error日誌出現資料庫連線異常,而實際交易量似乎並沒有到達耗盡連線池的地步。在詳細說明上述故障之前,需要簡單描述一樣具體的業務場景,大概是這樣:資料中某個欄位無值,不符合正常設計推理的流程。
資料出現詭異的結果,和關聯的業務日誌顯示的完全不一樣,業務日誌顯示成功,資料庫記錄卻是成功。
我們系統需要和外部系統進行互動,互動的過程中會在日誌和資料庫中都記錄交易的狀態,使用mq訊息佇列互動。第乙個問題,資料庫連線異常,相關人員分析了很久後也沒能找出是什麼原因,導致當前交易量的情況下就連線耗盡。資料庫涉及到的關鍵字段是:status代表狀態,time代表響應時間;
傳送請求前,status設定為02,代表「收到請求,本系統處理中」;
傳送請求並接到同步響應後,status設定為03,代表「請求成功,外部系統處理中」,同時記錄響應時間time;
收到外部系統非同步結果,結果是成功,status設定為00,代表「外部系統業務處理成功」;
收到外部系統非同步結果,但結果是失敗,status設定為01,代表「外部系統業務處理失敗」;
第二個問題,因為同步響應才會儲存time欄位,非同步通知不會儲存time欄位。
正常流程是先有同步響應後修改資料庫,而後才是非同步通知修改資料庫,會進行status的判斷。
但是出現問題的時候發現是非同步通知先改資料庫,同步響應後改,就導致status判斷不過。這個問題是程式本身的缺陷所在,算是找到了解決辦法。但是是什麼原因導致了非同步在前,同步在後?這又是乙個未解問題。
第三個問題,一樣是相關人員定位了很久,無法想通究竟是什麼原因導致日誌都成功的情況下,資料庫欄位是失敗。
直到這三個問題聚合到一起,關聯起來之後,才有資料庫比較熟的同事發現了問題所在,這三個詭異的問題,實際上都是同乙個問題導致,那就是sql語句中and和or使用不當,出了優先順序的隱秘問題。
這個修改資料庫的sql在mybits中大概是這樣的:
update table1這個sql的問題就在於,and的優先順序高於or,同時使用了and和or的情況下,這裡or前後的條件本該是整體,卻沒有用括號括起來。status=#,
time=#,
where
name=#
and age=#
and status="01" or status="02"
導致or前邊所有and連線的條件成了整體,就直接導致當status=『01』不成立的情況下,就只剩下了乙個條件,status=「02」。
然後這個操作就會更新資料當前status為02的所有記錄,由一條變成了n條。
於是乎,就大大增加了資料庫的負荷,使得原本可能只需消耗很短時間的update操作變得異常耗時,緊接著就導致後續很多資料庫操作陸續從連線池獲取連線,並且得不到釋放,直到連線耗盡,出現第乙個連線異常的問題。
同樣的,由於資料庫連線的問題,導致同步響應的更新操作一直等待,mq訊息就無法消費,產生堆積。又由於同步響應和非同步通知的mq佇列不同,就導致最終非同步通知mq佇列先消費,同步響應的mq佇列後消費,然後再加上程式本身的缺陷,導致第二個生產故障。
也是因為這樣,原本可能根據name條件只update符合條件的一條資料,結果變成了更新所有status是02的資料,就會導致其他失敗的訂單更新資料庫時,把其他訂單的status也更新成失敗,就會出現其他訂單日誌和資料庫記錄不一致的第三個生產故障。
實際上分析出問題根本原因後,解決起來就很簡單了,最簡單的,就是把or優先順序低的整體用括號括起來,如下:
update table1status=#,
time=#,
where
name=#
and age=#
and (status="01" or status="02")
記一次資料庫的實戰
話不多說 直接開始 開始我們的敲 的工程吧 首先匯入標頭檔案 import tkinter import tkinter.messagebox import pandas as pd import numpy as np import matplotlib.pyplot as plt from sk...
記一次資料庫事務鎖
最近在做專案的時候碰到乙個問題,事務鎖。transactionoptions tos new transactionoptions tos.isolationlevel isolationlevel.repeatableread 行鎖 只會鎖住當前操作的那一行資料,當前表的其他資料不受影響。已驗證 ...
記一次資料庫編碼問題修改
由於線上資料庫在建立的時候編碼格式沒有指定成正確的utf 8導致出現了以下問 需要進行資料庫編碼的修改。首先檢視資料庫的編碼。其中 database 就是資料庫的編碼。現在我們需要對資料庫的編碼進行修改可以使用 alter database db01 character set utf8 其中 db...