百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

MySQL Json有哪些缺点 mysql json类型对应java什么类型

liuian 2024-12-26 15:05 21 浏览

讨伐 json

今天的分享是再批 json, 去年分享过因为 mysql json 导致的故障,今天的 case 其实是去年的姊妹篇,原理一模一样。有两个原因不建议用 json:

  • Table Schema 就是强一致的,约束开发不要乱搞,json 这种弱约束的就是开后门,时间一长 json 字段就成了下水道
  • MySQL JSON 很垃圾,5.7 系列都有性能问题,测试 8.0 好很多。强烈建义大家,使用前压测一下
  • 上面提到的两点有争议?有争议就对了,一致认同是垃圾的东西谁会讨论它呢?

    实现

    JSON 有两种表示方法:文本可读的在 mysql 中对应 json_dom.cc, binary 二进制表示的对应 json_binary.cc

    If the value is a JSON object, its binary representation will have a 
    header that contains: 
     
    - the member count 
    - the size of the binary value in bytes 
    - a list of pointers to each key 
    - a list of pointers to each value 
     
    The actual keys and values will come after the header, in the same 
    order as in the header. 
     
    Similarly, if the value is a JSON array, the binary representation 
    will have a header with 
     
    - the element count 
    - the size of the binary value in bytes 
    - a list of pointers to each value 

    源码中注释也写的比较清楚,二进制分成两部分 header + element. 实际上 mysql 只是 server 识别了 json, 各个存储引擎仍存储的二进制 blob

    换句话说,底层引擎对 json 是无感知的,就是一条数据而己

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

    我们的问题

    MySQL Client 读取 json 时是 json_dom 调用 wrapper_to_string 方法,序列化成可读格式数据

    写入 json 时,是由 json_binary 调用 serialize_json_value 方法,序列化成上面图表示的 binary 数据,然后由引擎层存储成 blob 格式

    去年故障也有服务端的问题:加载单条数据失败主动 panic, 坑人不浅 (理由是数据不一致,宁可不对外提供服务,问题是那条数据恰好是重不重要的一类)。所以这个故事告诉我们: 在线服务的可用性,远高于数据一致性

    慢的原因是 wrapper_to_string 遇到 json array 特别多的情况下反复 mem_realloc 创建内存空间,导致性能下降

    其实去年没有 fix 完整,最近发现写入也有类似问题,只不过是 serialize_json_value 写入存储引擎前反复 mem_realloc 造成超时。这时前端页面发现写入超时了,(人工)重试继续写入 json 数据

    恰好赶上联合索引中有 NULL 字段,由此引出了唯一索引不唯一的现象。那怎么解决呢?前端按钮 cooldown 治标不治本,sql 执行 12s 前端肯定又点击提交了,治本还得升级 mysql 8.0 并且移除 NULL 字段, 那会不会又引入其它问题呢?

    项目初期做了错误的决定,后人很容易买单。希望我们踩到的坑,能让你决定使用 json 前犹豫几秒钟 ^^

    8.0 fix

    在测试机上发现 8.0 是 ok 的,没有性能问题,查看提交的 commit, 2016 年就有人发现并 fix 了,不知道有没有 back port 到 mysql 5.7 那几个版本

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

    参考资料

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

    MySQL Json有哪些缺点 | 《Linux就该这么学》 (linuxprobe.com)

    相关推荐

    10种常见的MySQL错误,你可中招?

    【51CTO.com快译】如果未能对MySQL8进行恰当的配置,您非但可能遇到无法顺利访问、或调用MySQL的窘境,而且还可能给真实的应用生产环境带来巨大的影响。本文列举了十种MySQL...

    MySQL主从如何保证数据一致性

    MySQL主从(主备)搭建请点击基于Spring的数据库读写分离。MySQL主备基本原理假设主备切换前,我们的主库是节点A,节点B是节点A的备库,客户端的读写都是直接访问节点A,节点B只是将A的更新同...

    MySQL低版本升级操作流程

    (关注“数据库架构师”公众号,提升数据库技能,助力职业发展)0-升级背景MySQL5.5发布于2010年,至今已有十年历史,官方已经停止更新。2008年发布的MySQL5.1版本,在2018年...

    MySQL数据库知识

    MySQL是一种关系型数据库管理系统;那废话不多说,直接上自己以前学习整理文档:查看数据库命令:(1).查看存储过程状态:showprocedurestatus;(2).显示系统变量:show...

    Mysql 8.4数据库安装、新建用户和数据库、表单

    1、下载MySQL数据库yuminstall-ywgetperlnet-toolslibtirpc#安装wget和perl、net-tools、libtirpcwgethtt...

    mysql8.0新功能介绍

    MySQL8.0新特性集锦一、默认字符集由latin1变为utf8mb4在8.0版本之前,默认字符集为latin1,utf8指向的是utf8mb3,8.0版本默认字符集为utf8mb4,utf8默...

    全网最详细解决Windows下Mysql数据库安装后忘记初始root 密码方法

    一、准备重置root的初始化密码Win+R键启动命令输入窗口;输入cmd打开命令执行窗口;##界面如下##输入命令:netstopmysqld#此操作会停止当前运行的...

    互联网大厂面试:MySQL使用grant授权后必须flush privilege吗

    从我上大学时,数据库概论老师就告诉我,MySQL使用grant对用户授权之后,一定记得要用flushprivilege命令刷新缓存,这样才能使赋权命令生效。毕业工作以后,在很多的技术文档上,仍然可以...

    # mysql 8.0 版本无法使用 sqlyog 等图形界面 登录 的解决方法

    30万以下的理想L6来了##mysql8.0版本无法使用sqlyog等图形界面登录的解决方法当我们在cmd下登录mysql时正常时,用sqlyog等图形界面连接数据库时却...

    MySQL触发器介绍

    前言:在学习MySQL的过程中,可能你了解过触发器的概念,不清楚各位是否有详细的去学习过触发器,最近看了几篇关于触发器的文档,分享下MySQL触发器相关知识。1.触发器简介触发器即trigg...

    管理员常用的MySQL命令汇总(一)

    以下是管理员常用的MySQL命令:以管理员身份连接到MySQL:mysql-uroot-p创建新的MySQL用户:CREATEUSER'username'@'...

    Linux(CentOS) 在线安装MySQL8.0和其他版本,修改root密码

    一:安装MySQL数据库1),下载并安装MySQL官方的YumRepositorymysql官方仓库地址:https://dev.mysql.com/downloads/repo/yum/选择自...

    解决 MySQL 8.0 一直拒绝 root 登录问题

    Accessdeniedforuser'root'@'localhost'(usingpassword:YES)这个错误在网上搜一下,能看到非常多的此类...

    大模型MCP之MYSQL安装

    前言学习大模型的时候需要一个mysql,原因还是在公司使用电脑的时候不允许按照Docker-Desktop,我的宿主机其实是MAC,我习惯上还是在centsos上面安装,就发现这件过去很简单的事情居然...

    MySQL ERROR 1396

    ERROR1396(HY000):OperationCREATEUSERfailedfor'usera'@'%'问题描述mysql>create...