ARTS #62

Algorithm

139. 單詞拆分

func wordBreak(s string, wordDict []string) bool {
    wordDictMap := make(map[string]bool)
    for _, v := range wordDict {
        wordDictMap[v] = true
    }
    results := make([]bool, len(s)+1)
    results[0] = true
    for i := 1; i <= len(s); i++ {
        results[i] = false
        for j := 0; j < i; j++ {
            _, ok := wordDictMap[s[j:i]]
            if results[j] && ok {
                results[i] = true
                break
            }
        }
    }
    return results[len(s)]
}

Review

Write a Web Service with Go Plug-Ins
文章介紹了go-plugin的入門使用方法,可用于即插即用的功能。

TIP

最近在項(xiàng)目開發(fā)中遇到一個(gè)需求:

  1. 前端頁面有多行操作記錄,這些記錄有先后順序的概念
  2. 可以對這些操作記錄進(jìn)行增刪改查功能。
  3. 對這些操作記錄,還需要支持拖拽改變先后順序的操作。

增刪改查都還好說,數(shù)據(jù)庫中對對應(yīng)的row進(jìn)行create、delete、update就可以了,難點(diǎn)在于如何實(shí)現(xiàn)“記錄有先后順序”這個(gè)需求。假設(shè)原來有2行操作記錄:

主鍵ID 記錄內(nèi)容 是否刪除
1 內(nèi)容1 false
2 內(nèi)容2 false

現(xiàn)在如果要將記錄2拖動到記錄1的前面,代碼和sql要如何編寫呢?經(jīng)過查閱資料,想到一個(gè)鏈表的結(jié)局方案。
簡單來說就是在數(shù)據(jù)庫中增加一個(gè)next_record_id字段,用來標(biāo)識這個(gè)節(jié)點(diǎn)指向的下一個(gè)節(jié)點(diǎn),然后再在代碼中通過拼接鏈表的方式將所有record進(jìn)行排序再輸出給前端。修改后的數(shù)據(jù)庫設(shè)計(jì)如下:

主鍵ID 記錄內(nèi)容 是否刪除 next_record_id
1 內(nèi)容1 false 2
2 內(nèi)容2 false -1

這里需要注意的是我們需要用-1來代表這一行數(shù)據(jù)為尾節(jié)點(diǎn)。
引入了next_record_id字段之后,對增刪改都增加了一定并發(fā)復(fù)雜度,原來增加一個(gè)節(jié)點(diǎn)只需要寫一個(gè)create sql就好了,但是現(xiàn)在需要如下操作:

  1. 前端調(diào)用后端add接口,傳入需要增加的信息,同時(shí)需要告訴后端pre_record_id,也就是目前前端上認(rèn)為的尾節(jié)點(diǎn)。
  2. 通過for update將原本的尾巴節(jié)點(diǎn)節(jié)點(diǎn)1鎖住,避免其他并發(fā)操作修改節(jié)點(diǎn)1。同時(shí)對節(jié)點(diǎn)1加鎖的for update語句需要在where 條件中加上 next_record_id=-1的樂觀鎖來避免節(jié)點(diǎn)1已經(jīng)被其他用戶update過了。完整sql應(yīng)該是:select ID from xxx where next_record_id=-1 for update.
  3. 執(zhí)行create sql增加一個(gè)新的尾巴節(jié)點(diǎn)節(jié)點(diǎn)2。
  4. update原本的尾部節(jié)點(diǎn)1的next_record_id字段指向新增的節(jié)點(diǎn)2。
  5. 需要特別注意的是以上所有操作需要在一個(gè)數(shù)據(jù)庫事務(wù)里面。

其他的刪改拖拽操作也是一樣的:老節(jié)點(diǎn)加鎖、對需要更新的節(jié)點(diǎn)進(jìn)行更新、修改相關(guān)record的next_record_id。

Share

學(xué)習(xí)mysql 45講

29 | 如何判斷一個(gè)數(shù)據(jù)庫是不是出問題了?

select 1判斷

定期執(zhí)行select 1并關(guān)注是否成功返回。本方法只能說明這個(gè)庫的進(jìn)程還在, 并不能說明主庫沒問題。

查表判斷

在系統(tǒng)庫(mysql庫) 里創(chuàng)建一個(gè)表, 比如命名為health_check, 里面只放一行數(shù)據(jù), 然后定期執(zhí)行,通過更新語句是否能夠成功來判斷數(shù)據(jù)庫是否有問題。
更新事務(wù)要寫binlog, 而一旦binlog所在磁盤的空間占用率達(dá)到100%, 那么所有的更新語句和事務(wù)提交的commit語句就都會被堵住。 但是, 系統(tǒng)這時(shí)候還是可以正常讀數(shù)據(jù)的。因此這個(gè)方案發(fā)現(xiàn)不了磁盤堵塞問題。

更新判斷

常見做法是放一個(gè)timestamp字段, 用來表示最后一次執(zhí)行檢測的時(shí)間。 這條更新語句類似于:update mysql.health_check set t_modified=now(); 通過判斷更新語句是否成功來判斷數(shù)據(jù)庫是否存在問題。
這個(gè)方案如果存在雙M架構(gòu)的話,主庫A和備庫B都用相同的更新命令, 就可能出現(xiàn)行沖突, 也就是可能會導(dǎo)致主備同步停止。為了讓主備之間的更新不產(chǎn)生沖突, 我們可以在mysql.health_check表上存入多行數(shù)據(jù), 并用A、 B的server_id做主鍵。

內(nèi)部統(tǒng)計(jì)

MySQL 5.6版本以后提供的performance_schema庫, 就在file_summary_by_event_name表里統(tǒng)計(jì)了每次IO請求的時(shí)間。我們可以通過打開對應(yīng)的檢測開關(guān)來記錄IO請求時(shí)間,從而及時(shí)發(fā)現(xiàn)暴露問題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容