关于mysql中字段类型为text文本存储json格式数据,字段被截断的问题

背景:

  1. 字段类型 MEDIUMTEXT

  2. 确定存储内容5548个字符,换算为字节不超过16M

  3. 数据库内已经存在更长内容的存储成功,短的内容存储失败

  4. 有几率出现截断概率,

  5. 日志看入库前参数json都是完整的,入库后内容被截断,导致前端读取数据结构解析失败而报错

发生这种情况的原因有两种可能:

1. 建表时数据库字段设置长度不足

  • 当输入内容的字符长度大于当前字段设置长度时,数据库会自动截断内容
  • 字段类型以下几种:

  • 字符串类型

类型 范围 说明  
Char(N) [ binary] N=1~255 个字节 binary :分辨大小写 固定长度 std_name cahr(32) not null
VarChar(N) [binary] N=1~255 个字节 binary :分辨大小写 可变长度 std_address varchar(256)
TinyBlob 最大长度255个字节(2^8-1) Blob (Binary large objects) 储存二进位资料,且有分大小写 memo text not null
TinyText 最大长度255个字节(2^8-1)
Blob 最大长度65535个字节(2^16-1)
Text 最大长度65535个字节(2^16-1)
MediumBlob 最大长度 16777215 个字节(2^24-1)
MediumText 最大长度 16777215 个字节(2^24-1
LongBlob 最大长度4294967295个字节 (2^32-1)
LongText 最大长度4294967295个字节 (2^32-1)
Enum 集合最大数目为65535 列举(Enumeration),Enum单选、Set复选 sex enum(1,0) habby set(‘玩电玩’,’睡觉’,’看电影’,’听音乐’)
Set 集合最大数目为64
  • 数字/数值类型
类型 范围 说明
TinyInt[M] [UNSIGNED] -128~127 UNSIGNED : 0~255 num tinyint unsigned
SmallInt[M] [UNSIGNED] -32768~32767 UNSIGNED :0~ 65535  
MediumInt[M] [UNSIGNED] -8388608~8388607 UNSIGNED :0~16777215  
Int[M] [UNSIGNED] -2^31~2^31-1 UNSIGNED : 0~2^32  
BigInt[M] [UNSIGNED] -2^63~2^63-1 UNSIGNED : 0~2^64  
Float [(M,D)] -3.4E+38~3.4E+38( 约 )

注: M 为长度, D 为小数,Float 4 bytes,Double 8 bytes Double [(M,D)] -1.79E+308~1.79E+308( 约 )Decimal [(M,D)] 辨別ZeroFill:当宣告关键字ZeroFill为自动填满0,如 000021

  • 日期时间类型
类型 范围
Date 日期(yyyy-mm-dd)
Time 时间(hh:mm:ss)
DateTime 日期与时间組合(yyyy-mm-dd hh:mm:ss)
TimeStamp yyyymmddhhmmss
Year 年份yyyy
  • 根据计算转换字符长度可知,并没有超过长度限制,故此种原因排除

2. 字符编码格式数据库不支持

  • 原数据库字符集设置为CHARSET=utf8,有些数据编码格式例如emoji的表情符号mysql 中的utf8并不支持
  • 据官方文档的解释:

    mysql 支持的 utf8 编码最大字符长度为 3 字节,如果遇到 4 字节的宽字符就会插入异常了。三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xffff,也就是 Unicode 中的基本多文种平面(BMP)。

  • 也就是说,任何不在基本多文本平面的 Unicode字符,都无法使用 Mysql 的 utf8 字符集存储。包括 Emoji 表情(Emoji 是一种特殊的 Unicode 编码,常见于 ios 和 android 手机上),和很多不常用的汉字,以及任何新增的 Unicode 字符等等。

  • 观察日志数据发现linux下打印出的日志存在类似 <u+1f44d> 样式的字符,属于unicode编码的特殊字符,文本内容也是在此截断的,由此可以判断为字符编码格式问题

3. 解决方案

3.1 升级 mysql 版本,并将utf8字符集升级到utf8mb4

升级你的 mysql 到 5.5.3 之后即可,查看当前环境版本:

  1. select version();
  • MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。好在utf8mb4是utf8的超集,除了将编码改为utf8bp4外不需要做其他转换。当然,为了节省空间,一般情况下使用utf8也就够了。
  • 所以好的技术就是,采用对当前而言最好的解决方案,然后再逐步迭代满足新的需求。

3.1.1 直接修改表结构

  1. --修改数据库字符集
  2. ALTER DATABASE test CHARACTER SET = utf8mb4;
  3. --修改表字符集
  4. alter table test convert to character set utf8mb4;
  5. --修改字符字符集
  6. ALTER TABLE `test` CHANGE COLUMN `name` `name` varchar(12) CHARACTER SET utf8mb4;

3.1.2 修改数据库默认配置

  1. [client]
  2. default-character-set = utf8mb4
  3. [mysqld]
  4. character-set-server=utf8mb4
  5. collation-server=utf8mb4_unicode_ci
  6. [mysql]
  7. default-character-set = utf8mb4

3.2 修改数据库字段类型

修改字段类型为二进制存储,通过样可以达到目的,进行兼容

  1. --修改字符字符集
  2. ALTER TABLE `test` CHANGE COLUMN `name` `name` MediumBlob ;

3.3 强行过滤掉生僻字符串

  • 从业务和技术的角度综合考虑,可以做个折中,将生僻字符串提前过滤掉,因为这类字符串本来就使用的很少,即使存进数据库了,展示、查询的时候也会多少有其它的问题,不如直接过滤掉,mysql 不支持四字节的 utf8 一方面可能是历史包袱,另一方面估计也是为了省空间。

有意者可以进行测试

  1. 先向在数据库中建表以utf8字符集,字段设置为二进制文本类型或者

    1. CREATE TABLE `ts_test` (
    2. `id` int(10) NOT NULL,
    3. `content` text NOT NULL CHARACTER SET utf8mb4, --或者 `content` BLOB NOT NULL,
    4. PRIMARY KEY (`id`)
    5. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
  2. 插入表情符号emoji

    1. insert into ts_test ('id','content') values (1,'aaaaaaaa
    2. msyql存储数据时字段被截断的更多相关文章

        1. PHPExcel导出数据时字段超过26列出错Invalid cell coordinate [1
        1. http://blog.csdn.net/dl425134845/article/details/46650961 以下是解决方案函数 /** *   方法名:    getExcel *   作用  ...

        1. python 大量使用json 存储数据时,格式化输出的方式
        1. import json, pprint dic = {'name': 234, 'user_name': 'yan xia ting yu ', 'list': ['ds', 'a', 2], '你好 ...

        1. PlayerPrefs存储数据在本地的存储位置
        1. PlayerPrefs存储数据时,其在windows的存储路径是注册表: HKEY_CURRENT_USER Software CompanyName ProjectName 其中的CompanyNa ...

        1. sql server的缺陷 将截断字符串或二进制数据 哪个字段
        1. 将截断字符串或二进制数据 哪个字段 消息 8152,级别 16,状态 14,第 2 行将截断字符串或二进制数据. sql server2000 sql server2014 也不能直接提示出哪个字段的 ...

        1. MySQLload data local infileMySQL数据库中导入数据时,无法导入和字段不分离问题。
        1. 利用load data将文件中的数据导入数据库表中的时候,遇到了两个问题. 首先是load data命令无法执行的问题: 命令行下输入load data local infile "path ...

        1. MSSQL导入数据时,出现“无法截断表 因为表正由Foreign key引用”错误
        1. * 错误 0xc002f210: 准备 SQL 任务: 执行查询“TRUNCATE TABLE [dsc100552_db].[dbo].[ALV_SalesBigClass] ”失败,错误如下:“无 ...

        1. 在向"带有自增字段的数据库表"中插入数据时,自定义"该自增字段"的数据
        1. 在设计数据库表的时候,经常会使用自增主键或其他自增字段.比如: DB_UserGroups表中GroupID为该表主键,并为自增字段. 但在将某字段设置自增后,想在插入数据时,人为指定自增字段的数据内 ...

        1. Android提供了5种方式存储数据:
        1. --使用SharedPreferences存储数据: --文件存储数据: --SQLite数据库存储数据: --使用ContentProvider存储数据: --网络存储数据: 一:使用SharedP ...

        1. Android开发手记(18) 数据存储三 SQLite存储数据
        1. Android为数据存储提供了五种方式: 1.SharedPreferences 2.文件存储 3.SQLite数据库 4.ContentProvider 5.网络存储 SQLite 是以嵌入式为目的 ...

      1. 随机推荐

          1. 用JS在html页面实现打印功能
          1. 首先在head里面加入下面一段js代码: <script language="javascript"> function preview(oper) { if (ope ...

          1. 初学Shiro
          1. Shiro Shiro是什么? Apache Shiro是Java的一个安全(权限)框架. Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境下,也可以用者JavaEE环境下 ...

          1. Eclipse4JavaEE配置Tomcat运行环境
          1. 如果我们想搭一个网站,我们可以使用Eclipse for JavaEE IDE进行开发. 初次使用需要配置网站的运行环境,可以去Apache官网下载Tomcat 8.5或Tomcat 9的版本 然后打 ...

          1. 【spring实战第五版遇到的坑】3.2中配置关系映射时,表名和3.1中不一样
          1. 3.2章中按照书中的步骤写好相应类的映射关系,发现启动时,之前在3.1章中建的表全部被删重新建立了,并且Ingredient表的数据没了,由于使用了JPA,默认使用的是hibernate,在启动时会删 ...

          1. React-组件的生命周期详解(含React16版本)
          1. 在一个组件的整个生命周期中,通过用户的交互来更新state或者props,重新渲染组件,更新页面的ui.组成一个简单的"状态机". react的生命周期三个阶段: Mounting ...

          1. 如何搭建基于C#和 Appium 的 Android自动测试环境
          1. 本文由葡萄城技术团队于博客园原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 如果想做手机端的自动化测试,Appium是首选的测试框架,因为网上使 ...

          1. Spinner之下拉多选,监听ID后显示不同Frgment页面
          1. 本人安卓小白,公司最近项目需要用到不同的类型的用户注册,周末下午写完记录一下. 网上找了一堆没有适合自己的(或者说我没找到),写的比较基础,欢迎大家多多指导. 老规矩,先上效果图 网上在线合成的GIF ...

          1. Eclipse 新建jsp文件报错问题
          1. 今天在web工程中新建一个index.jsp文件时,发现会报错,记录一下解决办法. 原因:缺少servlet-api.jar包 所以我们先去下载一个jar包,将它引入我们的工程中,即可. 工程右键-& ...

          1. vscode指定扩展安装位置
          1. 默认情况下,(Windows)vscode的安装路径为C:\Users\用户名\.vscode\extensions. 如果想要自定义扩展的安装路径,无法直接在vscode中修改.但是,在启动vsco ...

          1. HTML基础-------HTML标签(1)
          1. HTML标签(1) h系列(容器级双标签) h系列标签分为六个等级(h1,h2,h3,h4,h5,h6) 语义:给文本添加一个标题 标题重要程度逐级递减,一个页面只能有一个h1级的标签,并且大多数时候 ...