mysql number类型引号问题

简介:

背景

 这几天在做数据自动化同步测试过程,发现一个诡异的现象。一批100条语句的更新过程中,同步到目标库去执行,总会有几条记录出现更新失败。

原因

1. 查看了同步过程中的执行日志,也米有啥特别明显的问题,单就是update affect = 0 。

2. 问题的查找方式也是比较简单,针对底层执行的update语句,挨个字段确认,到底是哪一个字段影响了记录的定位。 最后发现是一个Decimal(19,8)的字段类型。

3. debug跟踪了下对应的mysql driver代码,发现针对setBigDecimal类型数据处理时,多了个单引号,字段内容就变成了 '1234.12312'.  测试过程中手工去除引号,就可以正常的update. 

 

测试

1.1.创建表  
2.mysql> create table ljhtable2 ( ID int(11) auto_increment , NUMBER_VALUES decimal(19,8) , CONSTRAINT ljhtable2_pk PRIMARY KEY(id) );  
3.  
4.2. 插入记录  
5.mysql> insert into ljhtable2 values(1, 4005747665.56665202);  

查询


1.mysql> select * from ljhtable2 ;  
2.+----+---------------------+  
3.| ID | NUMBER_VALUES       |  
4.+----+---------------------+  
5.|  1 | 4005747665.56665202 |  
6.+----+---------------------+  
7.1 row in set (0.00 sec)  
8.  
9.mysql> select * from ljhtable2 where number_values = '4005747665.56665202'; #加了引号就无法查询到  
10.Empty set (0.00 sec)  
11.  
12.mysql> select * from ljhtable2 where number_values = 4005747665.56665202;  
13.+----+---------------------+  
14.| ID | NUMBER_VALUES       |  
15.+----+---------------------+  
16.|  1 | 4005747665.56665202 |  
17.+----+---------------------+  
18.1 row in set (0.00 sec)  

深度分析

1. 资讯了下公司的资深的mysql DBA,针对加引号的处理,目前mysql的版本存在一些bug,我们使用的mysql 版本(5.1.41),所以只能通过mysql driver层面进行修复。 

2. mysql driver我们使用了server-side preparestatment + batch处理,问题就出在这里 (参数介绍: mysql几个参数(编码,预编译,批处理) )

 

这是我们使用的mysql driver参数


1.dbcpDs.addConnectionProperty("useServerPrepStmts", "true");  
2.dbcpDs.addConnectionProperty("rewriteBatchedStatements", "true");  

对应server-side的prepare实现类:ServerPreparedStatement .  

通过debug分析,在ServerPreparedStatement.toString()过程中针对Decimal类型,添加了引号,在跟踪了execute发送给mysql的数据包都是使用了writeLenString进行处理,不过看了下针对int,long,float类型也没有明确的类型标识,估计是在mysql server端进行类型转换处理,刚好类型转换又有些bug,就触发了上面的问题。

 

发送数据包的格式代码:ServerPreparedStatement.storeBinding()

解决

去掉上面的两项配置定义,使用mysql的client-side模式进行处理,由客户端拼装好sql,直接到mysql上进行执行。针对client-side的batch的一些优化处理,可以参见PreparedStatement.executePreparedBatchAsMultiStatement方法

考虑

目前mysql driver默认的都是基于client-side模式进行处理,可参见mysql driver changelog: http://dev.mysql.com/doc/refman/5.1/en/cj-news-5-0-5.html 

5.0.5的版本里提到: 


1.Due to a number of issues with the use of server-side prepared statements, Connector/J 5.0.5 has disabled their use by default. The disabling of server-side prepared statements does not affect the operation of the connector in any way  

client-side和server-side的性能差别:

1. server-side需要和服务端的2次网络交互,一次进行prepare statement的构建过程,一次发送具体的bind数据。服务端可以缓存对应的prepare statement内容

2. client-side只需要一次和服务端的网络交互,但每次的sql都需要在服务端进行parse

 

所以针对server-side模式,如果不在jdbc客户端层面开启prepare statement cache,性能还不如client-side模式。而dbcp开启prepare statement cache,可能又会引发另外的问题: statement异常关闭。 在之前的dbcp测试过程中遇到过,后来就关闭了dbcp的prepare statement cache. 


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
Oracle 关系型数据库 MySQL
【YashanDB知识库】kettle从DM8的number类型同步到YashanDB的varchar类型,存入是科学计数法形式的数据
【YashanDB知识库】kettle从DM8的number类型同步到YashanDB的varchar类型,存入是科学计数法形式的数据
|
存储 SQL 关系型数据库
【YashanDB知识库】MySQL迁移至崖山char类型数据自动补空格问题
**简介**:在MySQL迁移到崖山环境时,若字段类型为char(2),而应用存储的数据仅为'0'或'1',查询时崖山会自动补空格。原因是mysql的sql_mode可能启用了PAD_CHAR_TO_FULL_LENGTH模式,导致保留CHAR类型尾随空格。解决方法是与应用确认数据需求,可将崖山环境中的char类型改为varchar类型以规避补空格问题,适用于所有版本。
|
关系型数据库 MySQL Java
【YashanDB知识库】崖山BIT类型对MYSQL兼容问题
【YashanDB知识库】崖山BIT类型对MYSQL兼容问题
|
自然语言处理 关系型数据库 MySQL
MySQL索引有哪些类型?
● 普通索引:最基本的索引,没有任何限制。 ● 唯一索引:索引列的值必须唯一,但可以有空值。可以创建组合索引,则列值的组合必须唯一。 ● 主键索引:是特殊的唯一索引,不可以有空值,且表中只存在一个该值。 ● 组合索引:多列值组成一个索引,用于组合搜索,效率高于索引合并。 ● 全文索引:对文本的内容进行分词,进行搜索。
|
机器学习/深度学习 关系型数据库 MySQL
mysql bit对gorm使用何种类型?
在GORM中使用MySQL的BIT类型时,通常使用 `bool`类型来处理BIT(1),使用 `[]byte`类型来处理BIT(N)(N > 1)。通过正确的类型映射和位操作,可以高效地处理位字段数据。确保在定义结构体字段时,明确指定字段类型,以便GORM能够正确地处理数据库交互。
471 18
|
存储 关系型数据库 MySQL
mysql怎么查询longblob类型数据的大小
通过本文的介绍,希望您能深入理解如何查询MySQL中 `LONG BLOB`类型数据的大小,并结合优化技术提升查询性能,以满足实际业务需求。
808 6
|
存储 SQL 关系型数据库
【YashanDB 知识库】MySQL 迁移至崖山 char 类型数据自动补空格问题
问题分类】功能使用 【关键字】char,char(1) 【问题描述】MySQL 迁移至崖山环境,字段类型源端和目标端都为 char(2),但应用存储的数据为'0'、'1',此时崖山查询该表字段时会自动补充空格 【问题原因分析】mysql 有 sql_mode 控制,检查是否启用了 PAD_CHAR_TO_FULL_LENGTH SQL 模式。如果启用了这个模式,MySQL 才会保留 CHAR 类型字段的尾随空格,默认没有启动。 #查看sql_mode mysql> SHOW VARIABLES LIKE 'sql_mode'; 【解决/规避方法】与应用确认存储的数据,正确定义数据
|
移动开发 关系型数据库 MySQL
MySQL中的ROW_NUMBER窗口函数简单了解下
ROW_NUMBER是 MySQL8引入的窗口函数之一,它为查询结果集中的每一行分配一个唯一的顺序号(行号)。ROW_NUMBER在分页、去重、分组内排序等场景中非常有用。
1490 4
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
715 158
|
关系型数据库 MySQL 数据库
自建数据库如何迁移至RDS MySQL实例
数据库迁移是一项复杂且耗时的工程,需考虑数据安全、完整性及业务中断影响。使用阿里云数据传输服务DTS,可快速、平滑完成迁移任务,将应用停机时间降至分钟级。您还可通过全量备份自建数据库并恢复至RDS MySQL实例,实现间接迁移上云。

推荐镜像

更多