一条诡异的insert语句
作者 | 天士梦
来源 | https://www.cnblogs.com/cchust/p/4601536.html
问题背景
有同事反馈在mysql上面执行一条普通的insert语句,结果报错,
execute failed due to >>> Incorrect string value: '\xA1;offl...' for column 'biz_info' at row 1
经过半天的折腾,终于搞清楚了来龙去脉,这里简单给大家分享下。为了方便说明,我将测试例子中的表和语句简化,但不影响问题重现。
问题复现
连接字符集:UTF8
表结构:
CREATE TABLE `ggg` (`id` int(11) DEFAULT NULL,`c` varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
root@test 06:13:48>insert into ggg values(1,concat('cardName:校园网',char(59),'offlineCardType:campus'));
Query OK, 1 row affected, 1 warning (2.51 sec)
root@test 06:14:36>show warnings\G
*************************** 1. row ***************************
Level: Warning
Code: 1366
Message: Incorrect string value: '\x91;offl...' for column 'c' at row 1
查看结果
root@test 06:16:06>select * from ggg where id=1;
*************************** 1. row ***************************
id: 1
c: cardName:鏍″洯缃
问题分析
从报错的结果来看,感觉是字符集转换引起的问题,而且由于连接串的字符集是UTF8,表的字符集是GBK,更容易引起怀疑。但是,即使是字符集转换,也不应该导致插入报错,因为语句中的中文字符“校园网"都是普通汉字,UTF8->GBK不应该存在问题。
那我们在回过头来看看insert语句,唯一特殊的是使用了concat和char两个函数。会不会跟这两个函数有关系?char(59)实际是字符“;”,为了验证想法,做了两个实验:
将char(59)替换成';'
insert into ggg values(1,concat('cardName:校园网',';','offlineCardType:campus'));
设置连接串字符集为GBK
insert into ggg values(1,concat('cardName:校园网',char(59),'offlineCardType:campus'));
果然,两种情况执行结果都是OK的,查询结果如下:
root@test 09:22:32>select * from ggg\G
*************************** 1. row ***************************
id: 1
c: cardName:鏍″洯缃
*************************** 2. row ***************************
id: 1
c: cardName:校园网;offlineCardType:campus
*************************** 3. row ***************************
id: 1
c: cardName:校园网;offlineCardType:campus
跟踪了下源代码,找到了原因。char()函数返回的是一个binary类型字符串,在进行concat时,会导致'cardName:校园网'字符串到binary的转换。转换前,mysql将字符串‘cardName:校园网’看作是9个英文字符和3个汉字字符;转换后,mysql将其看作是18个字节的二进制串,其中,UTF8字符集的三个汉字“校园网”占了9个字节。由于目标表字符集是GBK,因此在入库时,还会发生一次binary到GBK的转码,“校园网”的二级制编码是E6A0A1 E59BAD E58DA1,在转码过程中,由于GBK字符集只包含一个字节(编码值<128)和二个字节的字符(汉字和特殊字符),“校园网”的二进制串会按照两个字节拆分E6A0 A1E5 9BAD E58D A1,前面四个变为“鏍″洯缃”,解析到A1时,由于A1既不是单字节字符,又不能与后面的字节组成一个合法的GBK字符,导致转换出错。
现在就很好解释为啥改变语句后,两种情况都OK了。第一种情况,将char(59)直接替换成‘;’,由于不涉及UF8到binary的转换,只有utf8到gbk转码的过程,这个转换是OK的,不会出现乱码;第二种情况,将连接串的字符集设置为GBK,那么会涉及GBK到binary的转换,然后再从binary转换到GBK,由于整个转换过程并没有二进制数据丢失,所以也是OK的。
问题产生的两个关键点
连接字符集与表字符集不匹配
使用了char函数
解决办法
1.char函数提供了using语法来实现返回特定字符集的字符串,比如:char(59 using utf8)
2.保证连接字符集与表字符集一致。
往期推荐
Spring Boot 2.6之后,动态权限控制终于可以用起来了!
浪潮编了个“谎言”举报我们...
Spring Boot 2.6 正式发布:循环依赖默认禁止、增加SameSite属性...
一文教你如何高效使用 IDEA !
周杰伦新动作的老朋友是谁?程序员:送分题!
技术交流群
最近有很多人问,有没有读者交流群,想知道怎么加入。加入方式很简单,有兴趣的同学,只需要点击下方卡片,回复“加群“,即可免费加入我们的高质量技术交流群!
点击阅读原文,送你免费Spring Boot教程!
一条诡异的insert语句相关推荐
- INSERT 语句 增加条件,条件成立插入,否则不插入
不推荐用本文的方法 如果可以最好是为表增加 联合主键 ,本文介绍的方法会降低运行速度. 业务层插入数据,联合主键唯一 ,如果重复就插入失败,业务层通过查询确认信息是否已经插入即可. 问题描述: 遇到一 ...
- MySQL · 源码分析 · 一条insert语句的执行过程
本文只分析了insert语句执行的主路径,和路径上部分关键函数,很多细节没有深入,留给读者继续分析 create table t1(id int); insert into t1 values(1) ...
- 一条insert语句导致的性能问题分析(一)
今天早上开发找我看一个问题,说他们通过程序连接去查一个表的数据的时候,只查到了8条记录,这个情况着实比较反常,因为从业务上的数据情况来说,不可能只有8条. 但是开发没有太多的权限做线上环境的数据检查, ...
- mysql 8.0 一条insert语句的具体执行流程分析(三)
代码版本:mysql 8.0.22 编程语言:c++ && c++11 && c++14 && c++17 上一篇文章:mysql 8.0 一条inse ...
- mysql 8.0 一条insert语句的具体执行流程分析(二)
继续上一篇文章:mysql 8.0 一条insert语句的具体执行流程分析(一)_一缕阳光的博客-CSDN博客 由于最近换工作一直在试用期内,在拼命的学习.总结中,因此没有时间写文章,今天转正了腾出来 ...
- mysql 8.0 一条insert语句的具体执行流程分析(一)
最近在mysql 8.0的代码上开发新的功能的时候,梳理了insert语句的执行过程,由于insert语句比较复杂并且涉及的内容很多,在下面准备分3章节来分析,这是第一个章节,主要讲述sql解析和命令 ...
- mysql上一条语句成功_mysql : 获取上一条insert语句
在一些项目中 , 经常接触分表 . 比如 : 商品信息 和 商品的详情 , 是分开的两个表 . dt_mall和dt_mall_content; 当我dt_mall插入一条数据的时候 , 如果插入成功 ...
- oracle常用插入一条语句,Oracle:用一条 INSERT 语句批量插入多条记录
用一条 INSERT 语句批量插入多条记录,实例如下: 先建立这样一个表 T: SQL> DESC T Name Null? Type ---- ...
- 如何一次高效的插入200MB(50万条)的insert语句
那天老大给了我一个100M的一个txt文档,我点开后发现都是Insert语句,当时就懵了这插入不得卡死啊,况且服务器都是远程的. 之后我直接就把pl/sql等一些可视化操作界面都抛一边了,原因:可视化 ...
最新文章
- JavaScript的方法和技巧
- 计算php代码执行时间长短的类
- Windows服务二:测试新建的服务、调试Windows服务
- 排列组合十一个性质公式及证明,错排数公式及证明
- pandas学习笔记五之pandas合并
- POJ 1236 Network of Schools(强连通分量缩点求根节点和叶子节点的个数)
- Linux之特殊的环境变量IFS以及如何删除带有空格的目录
- Django ORM QuerySet集合对象的特性
- 洛谷——P1025 数的划分
- PHP实现单向链表解决约瑟夫环问题
- 【静态ip保姆级教程他来了】
- VM VirtualBox安装mac os dmg 转 iso
- 苹果官方付费升级内存_苹果6 Plus升级内存后遇到刷机报错40维修过程【详解】...
- Spring Boot 2.x 基础案例:整合Dubbo 2.7.3+Nacos1.1.3(配置中心)
- 一文带你了解什么是CDN?
- java新手抖机灵(java新手技巧)
- XTUOJ-1379 折纸-贰
- applecare多少钱?_AppleCare和AppleCare +有什么区别?
- html简单情侣对话
- Pr 案例:制作快闪转场效果
热门文章
- 协同工作流引擎,开启流程优化新纪元
- 利用Squid反向代理搭建CDN缓存服务器加快Web访问速度
- Linux命令之cal
- 不要对对象进行粗暴的等号赋值
- 通过Samba实现Win/Mac访问Linux
- SilverLight学习笔记--建立Silverlight自定义控件(5)--绑定动画效果
- spring MVC之返回JSON数据(Spring3.0 MVC+Jackson+AJAX)
- openssl 生成 cert.key cert.pem
- centos7 tomcat8 配置 java web环境 熵池不够大 启动慢问题
- linux 查本机公网ip 网站接口 nmap工具