自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

再批 MySQL Json

數(shù)據(jù)庫 MySQL
今天的分享是再批 json, 去年分享過因?yàn)?mysql json 導(dǎo)致的故障,今天的 case 其實(shí)是去年的姊妹篇,原理一模一樣。

本文轉(zhuǎn)載自微信公眾號(hào)「董澤潤(rùn)的技術(shù)筆記」,作者董澤潤(rùn)。轉(zhuǎn)載本文請(qǐng)聯(lián)系董澤潤(rùn)的技術(shù)筆記公眾號(hào)。

上一篇弱智的 MySQL NULL, 居然有小伙伴留言說,在業(yè)務(wù)中依賴 NULL 使聯(lián)合索引不唯一的特性,比如有的用戶就要多條記錄,有的僅一條。

我看了差點(diǎn)一口老血噴出來,把業(yè)務(wù)邏輯耦合在 DB 中這樣真的合適嘛? 要是外包另當(dāng)別論,正常項(xiàng)目誰接手誰倒霉。

討伐 json

今天的分享是再批 json, 去年分享過因?yàn)?mysql json 導(dǎo)致的故障,今天的 case 其實(shí)是去年的姊妹篇,原理一模一樣。有兩個(gè)原因不建議用 json:

  1. Table Schema 就是強(qiáng)一致的,約束開發(fā)不要亂搞,json 這種弱約束的就是開后門,時(shí)間一長(zhǎng) json 字段就成了下水道
  2. MySQL JSON 很垃圾,5.7 系列都有性能問題,測(cè)試 8.0 好很多。強(qiáng)烈建義大家,使用前壓測(cè)一下

上面提到的兩點(diǎn)有爭(zhēng)議?有爭(zhēng)議就對(duì)了,一致認(rèn)同是垃圾的東西誰會(huì)討論它呢?

實(shí)現(xiàn)

JSON 有兩種表示方法:文本可讀的在 mysql 中對(duì)應(yīng) json_dom.cc, binary 二進(jìn)制表示的對(duì)應(yīng) json_binary.cc

Binary Format

  1. If the value is a JSON object, its binary representation will have a 
  2. header that contains
  3.  
  4. - the member count 
  5. - the size of the binary value in bytes 
  6. - a list of pointers to each key 
  7. - a list of pointers to each value 
  8.  
  9. The actual keys and values will come after the header, in the same 
  10. order as in the header. 
  11.  
  12. Similarly, if the value is a JSON array, the binary representation 
  13. will have a header with 
  14.  
  15. - the element count 
  16. - the size of the binary value in bytes 
  17. - a list of pointers to each value 

源碼中注釋也寫的比較清楚,二進(jìn)制分成兩部分 header + element. 實(shí)際上 mysql 只是 server 識(shí)別了 json, 各個(gè)存儲(chǔ)引擎仍存儲(chǔ)的二進(jìn)制 blob

換句話說,底層引擎對(duì) json 是無感知的,就是一條數(shù)據(jù)而己

json-function-reference[1] 官方有好多在 server 層操作 json 的方法,感興趣的可以看一下

我們的問題

MySQL Client 讀取 json 時(shí)是 json_dom 調(diào)用 wrapper_to_string 方法,序列化成可讀格式數(shù)據(jù)

寫入 json 時(shí),是由 json_binary 調(diào)用 serialize_json_value 方法,序列化成上面圖表示的 binary 數(shù)據(jù),然后由引擎層存儲(chǔ)成 blob 格式

去年故障也有服務(wù)端的問題:加載單條數(shù)據(jù)失敗主動(dòng) panic, 坑人不淺 (理由是數(shù)據(jù)不一致,寧可不對(duì)外提供服務(wù),問題是那條數(shù)據(jù)恰好是重不重要的一類)。所以這個(gè)故事告訴我們: 在線服務(wù)的可用性,遠(yuǎn)高于數(shù)據(jù)一致性

慢的原因是 wrapper_to_string 遇到 json array 特別多的情況下反復(fù) mem_realloc 創(chuàng)建內(nèi)存空間,導(dǎo)致性能下降

其實(shí)去年沒有 fix 完整,最近發(fā)現(xiàn)寫入也有類似問題,只不過是 serialize_json_value 寫入存儲(chǔ)引擎前反復(fù) mem_realloc 造成超時(shí)。這時(shí)前端頁面發(fā)現(xiàn)寫入超時(shí)了,(人工)重試?yán)^續(xù)寫入 json 數(shù)據(jù)

恰好趕上聯(lián)合索引中有 NULL 字段,由此引出了唯一索引不唯一的現(xiàn)象。那怎么解決呢?前端按鈕 cooldown 治標(biāo)不治本,sql 執(zhí)行 12s 前端肯定又點(diǎn)擊提交了,治本還得升級(jí) mysql 8.0 并且移除 NULL 字段, 那會(huì)不會(huì)又引入其它問題呢?

項(xiàng)目初期做了錯(cuò)誤的決定,后人很容易買單。希望我們踩到的坑,能讓你決定使用 json 前猶豫幾秒鐘 ^^

8.0 fix

在測(cè)試機(jī)上發(fā)現(xiàn) 8.0 是 ok 的,沒有性能問題,查看提交的 commit, 2016 年就有人發(fā)現(xiàn)并 fix 了,不知道有沒有 back port 到 mysql 5.7 那幾個(gè)版本

  1. commit a2f9ea422e4bdfd65da6dd0c497dc233629ec52e 
  2. Author: Knut Anders Hatlen <knut.hatlen@oracle.com> 
  3. Date:   Fri Apr 1 12:56:23 2016 +0200 
  4.  
  5.     Bug#23031146: INSERTING 64K SIZE RECORDS TAKE TOO MUCH TIME 
  6.  
  7.     If a JSON value consists of a large sub-document which is wrapped in 
  8.     many levels of JSON arrays or objects, serialization of the JSON value 
  9.     may take a very long time to complete. 
  10.  
  11.     This is caused by how the serialization switches between the small 
  12.     storage format (used by documents that need less than 64KB) and the 
  13.     large storage format. When it detects that the large storage format 
  14.     has to be used, it redoes the serialization of the current 
  15.     sub-document using the large format. But this re-serialization has to 
  16.     be redone again when the parent of the sub-document is switched from 
  17.     small format to large format. For deeply nested documents, the inner 
  18.     parts end up getting re-serializing again and again. 
  19.  
  20.     This patch changes how the switch between the formats is done. Instead 
  21.     of starting with re-serializing the inner parts, it now starts with 
  22.     the outer parts. If a sub-document exceeds the maximum size for the 
  23.     small format, we know that the parent document will exceed it and need 
  24.     to be re-serialized too. Re-serializing an inner document is therefore 
  25.     a waste of time if we haven't already expanded its parent. By starting 
  26.     with expanding the outer parts of the JSON document, we avoid the 
  27.     wasted work and speed up the serialization. 

參考資料

[1]json-function-reference: https://dev.mysql.com/doc/refman/5.7/en/json-function-reference.html

 

責(zé)任編輯:武曉燕 來源: 董澤潤(rùn)的技術(shù)筆記
相關(guān)推薦

2025-03-04 00:36:00

2013-06-04 10:44:44

MySQL

2015-04-15 13:33:23

2021-10-19 10:26:31

MySQL.MySQLJSON

2010-06-02 17:39:49

MySQL數(shù)據(jù)讀取

2021-06-03 19:13:06

MySQLJson數(shù)據(jù)

2012-08-28 09:12:52

App瘦身

2023-09-12 07:28:47

MySQLJSON工具

2022-07-04 09:01:50

數(shù)據(jù)庫遷移

2023-10-25 14:51:38

MySQL數(shù)據(jù)庫JSON

2020-07-03 07:46:22

CPUOS內(nèi)存

2009-07-01 17:10:22

微軟Adobe

2013-06-05 09:04:00

SDN集中控制數(shù)據(jù)中心

2024-01-12 07:07:59

2017-04-06 09:59:51

戴爾集成

2010-06-10 14:26:20

云計(jì)算

2025-02-14 11:32:33

MySQL數(shù)據(jù)庫第一范式

2017-01-18 09:54:38

MySQLJson ColumnGenerated C

2021-06-02 16:29:29

華為MatePad Pro鴻蒙系統(tǒng)

2009-02-12 20:43:52

收購奇夢(mèng)達(dá)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)