`
agapple
  • 浏览: 1585667 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

mysql number类型引号问题

阅读更多

背景

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

原因

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

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

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

 

测试

 

1.创建表
mysql> create table ljhtable2 ( ID int(11) auto_increment , NUMBER_VALUES decimal(19,8) , CONSTRAINT ljhtable2_pk PRIMARY KEY(id) );

2. 插入记录
mysql> insert into ljhtable2 values(1, 4005747665.56665202);

 

 

查询

 

mysql> select * from ljhtable2 ;
+----+---------------------+
| ID | NUMBER_VALUES       |
+----+---------------------+
|  1 | 4005747665.56665202 |
+----+---------------------+
1 row in set (0.00 sec)

mysql> select * from ljhtable2 where number_values = '4005747665.56665202'; #加了引号就无法查询到
Empty set (0.00 sec)

mysql> select * from ljhtable2 where number_values = 4005747665.56665202;
+----+---------------------+
| ID | NUMBER_VALUES       |
+----+---------------------+
|  1 | 4005747665.56665202 |
+----+---------------------+
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参数

 

dbcpDs.addConnectionProperty("useServerPrepStmts", "true");
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的版本里提到

 

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. 

 

 

 

 

分享到:
评论

相关推荐

    解决python 执行sql语句时所传参数含有单引号的问题

    (\'%s\', \'%s\', \'%s\', \'%s\') % (result, result2, phoneNumber, Email) cur.execute(sql_str) 执行程序后,产生错误: ProgrammingError: (1064, “You have an error in your SQL syntax; check the m

    presto sql 与mysql sql 对比.pdf

    在 Presto SQL 中,字段名和表名使用双引号括起来,而在 MySQL SQL 中,字段名和表名使用反引号括起来。 函数 Presto SQL 和 MySQL SQL 都支持一些常用的函数,如日期函数、字符串函数、数学函数等。 * 日期函数...

    从mysql转换到oracle数据库.docx

    这样可以避免在 Oracle 数据库中出现问题。 二、对表的修改 在将 MySQL 表结构导出到 Oracle 数据库之前,我们需要对表结构进行修改。具体来说,有以下几点需要注意: 1. 去掉``,这是 MySQL 的特殊标示符。 2. ...

    mysql数据库的基本操作语法

    MySQL结束符是“;”结束。 1、 显示所有数据库 show databases; 2、 删除数据库 drop database dbName; 3、 创建数据库 create database [if not exists] dbName; 中括号部分可选的,判断该数据不存在就创建 4、 ...

    [php]mysql数据库操作——DB类

    【作 用】: mysql数据库操作类 【作 者】: Riyan 【版 本】: version 2.0 【修改日期】: 2010/02/11 ※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※ ※※※※※※※※ **/ class ...

    MySQL转换Oracle的需要注意的七个事项

    自动增长的数据类型处理 MySQL有自动增长的数据类型,插入记录时不用操作此字段,会自动获得数据值。Oracle没有自动增长的数据类型,需要建立一个自动增长的序列号,插入记录时要把序列号的下一个值赋于此字段。 ...

    MySQL语句笔记.doc

    1. 创建数据表:使用 `CREATE TABLE` 语句创建数据表,例如 `CREATE TABLE mydatabase.student (name VARCHAR(10), gender VARCHAR(10), number VARCHAR(10), age INT) CHARSET utf8;`。 2. 查看数据表:使用 `SHOW ...

    学习php过程中的一些注意点的总结

    ?...标签外面打上引号 document.getElementById(“titor”+a+b)[removed]=”<?...>”;...实际上为显示相关文本的echo里面,因为原来的不带引号,所以加引号是...关于数据的四舍五入 number_format($time*$deposit_money*0

    2009达内SQL学习笔记

    如果将值与串类型的列进行比较,则需要限定引号;用来与数值列进行比较时,不用引号。 is null:是空。(NULL表示不包含值。与空格、0是不同的。) 如:SELECT prod_name,prod_price FROM Products WHERE prod_...

    PHP基础教程 是一个比较有价值的PHP新手教程!

    如果你的机器解决了2000问题,那么PHP也一样没有千年虫问题! 1.1 历史 三年前,Rasmus Lerdorf为了创建他的在线简历而创造了"个人主页工具"(Personal Home Page Tools)。这是一种非常简单的语言。其后越来越多...

    入门学习Linux常用必会60个命令实例详解doc/txt

    在使用mount这个指令时,至少要先知道下列三种信息:要加载对象的文件系统类型、要加载对象的设备名称及要将设备加载到哪个目录下。 (1)Linux可以识别的文件系统 ◆ Windows 95/98常用的FAT 32文件系统:vfat ;...

    .htaccess

    许多主机支持.htaccess,但实际上并不会特别声明,许多其他类型的主机有能力但并不允许他们的用户使用.htaccess。一般来说,如果你的主机使用Unix或Linux系统,或任何版本的Apache网络服务器,从理论上都是支持....

Global site tag (gtag.js) - Google Analytics