文档章节

PDO写入十六进制数据导致数据库同步失败

Eric_chan
 Eric_chan
发布于 2015/05/05 18:17
字数 1171
阅读 24
收藏 0

警报响起:

               Last_SQL_Errno: 1062
               Last_SQL_Error: Error 'Duplicate entry '4294967295-2147483647-825241648' for key 'law_rea_pec'' on query. Default database: 'fuck_cn'. Query: 'INSERT INTO `u_law_pec` (`law_id`,`rea`,`pec`,`pec_sub`,`amount`,`stat`,`input_time`) VALUES (0x323036363434,0x323631333030,0x31303030,0x313030312C313030322C313030332C313030342C313030352C31303036,0x30,0x30,0x31343239383639323236)'

数据库同步挂了,整个体系瘫痪。

看到是有重复的值导致的,首先就跳过了一条记录。 再启动同步,可以同步了。ok

不一会 警报又响起了,还是一样的错误。

仔细一看 4294967295 已经是 int 无符号整形的最大值了。 INSERT语句里面还一堆的十六进制的字符串。

这个十六进制是怎么来的呢? 

如是查查日志,发现日志里面也是十六进制的,可以确认是PDO 连接类发过来的语句就是这样了。

首先是预处理,然后执行SQL语句,查询日志如下:

                Prepare INSERT INTO `u_law_pec` (`law_id`,`rea`,`pec`,`pec_sub`,`amount`,`stat`,`flag`,`input_time`) VALUES (?,?,?,?,?,?,?,?)
                Execute INSERT INTO `u_law_pec` (`law_id`,`rea`,`pec`,`pec_sub`,`amount`,`stat`,`flag`,`input_time`) VALUES (0x3330333034373335,0x313730333030,0x31323030,"",0x30,0x30,0x32,0x31343330383034343336)


通过这样去查看这些十六进制: 发现是可以正确解码的。

mysql> select 0x323036363434,0x323631333030,0x31303030,0x313030312C313030322C313030332C313030342C313030352C31303036,0x30,0x30,0x31343239383639323236;
+----------------+----------------+------------+--------------------------------------------------------------+------+------+------------------------+
| 0x323036363434 | 0x323631333030 | 0x31303030 | 0x313030312C313030322C313030332C313030342C313030352C31303036 | 0x30 | 0x30 | 0x31343239383639323236 |
+----------------+----------------+------------+--------------------------------------------------------------+------+------+------------------------+
| 206644         | 261300         | 1000       | 1001,1002,1003,1004,1005,1006                                | 0    | 0    | 1429869226             |
+----------------+----------------+------------+--------------------------------------------------------------+------+------+------------------------+

但是 INSERT 这个语句的时候发现写入的数据不对:

0x323036363434 对应的是 206644  却写入  4294967295

猜测是数据溢出了。  

0x323036363434 <16进制数值转10进制数值是>  55182649340980 远大于了INT 的最大值。

问题就在这里了:

  本来是需要十六进制转字符串文本的,结果mysql在这里把十六进制转成了十进制的数值。

因为表达式 x'test-string' (4.0 中新加入) 是基于 ANSI SQL 的,表达式 0x 是基于 ODBC 的, 所以我们没有使用ODBC的方式操作数据库的时候,就出现了上面的转储不正确的情况。


解决问题方法:

  1. PDO 传过来的数据用标准sql语句的文本格式,别搞些十六进制的字符串。

        通过对比实验发现 :

               Mysql5.6版本, PHP5.6 版本的 使用PDO 是不会出现上面的情况的。之前用的低版本的PHP带PDO 操作数据就会出现上面的问题。 所以 我们采用升级PHP版本的方式 解决这个问题。

--------------------------------------

今天发现之前也有路人甲遇到过此类问题并且分析的比较详细:

       访问 mysql server 的方式有两种。
       1、 直接访问模式
       2、 预处理模式
       先说说这两个结构的区别,直接访问就像我们用客户端连接进数据那样,标准的 sql 语句插入、更新、删除和查询。这个要求就是每个命令里面都要指明 表、字段、等信息。
       预处理就是:先告诉 mysql 一个表的结构,然后,后面的全都按照这个表结构来,这样就不用每次都发送 表、字段等信息了。这样的优势是大量的插入会快一点。特点是只在第一次发送表结构。而不是每次都发送一遍,问题是 mysql binlog 里面不支持这种格式。
       这两种方式比较起来,第一种 安全,第二种 快速 。第二种因为没有表结构,所以当任何一个字段出现问题,就会造成所有的数据问题,而不像第一种,只影响那一句。那个 PDO 使用的就是第二种方式,而且他错误的认为一切都是字符串,把所有的数据都转换成 16 进制了。
       在第一次插入的时候 mysql 使用第二种方式插入数据,但 binlog 里面因为没有这种结构,所以他自己把语句转换成了 第一种模式,加上了表、及字段信息,但 mysql 不会对 int 形做相应的转换,(这个在字符串表示中是没有错误的),造成了记录的日志是按照字符串的方式记录的。这样在吧一个字符串插入 int 形就出现了插入的数据和日志不一致的情况。要解决这个问题只有 1、给mysql 写一个补丁,解决这个问题。(现在功力不够还写不出来) 2、在我们公司禁用 预处理结构体方式的数据写入。看来目前我们只能使用第二种方法了。


       结论:
       总的来说,pdo 写的有问题,mysql 的 log 记录转换的方式也存在问题。下面是我写的一个能够触发这个 bug 的代码。

原文:http://blog.csdn.net/ugg/article/details/9042255

-------------------------------------------------









© 著作权归作者所有

共有 人打赏支持
Eric_chan
粉丝 0
博文 3
码字总数 1348
作品 0
广州
【原创】modb 中日志的设计

【日志格式】 在之前确定好通信所用的 json 数据格式后,到确定最终生成的日志内容的时候了。之前提到日志内容至少要包括下面几点: 日志记录的时间戳(在本地生成) 日志的“流向”(从哪里...

摩云飞
2014/01/23
115
0
【分布式】数据库和缓存双写一致性方案解析

引言 为什么写这篇文章? 首先,缓存由于其高并发和高性能的特性,已经在项目中被广泛使用。在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作。 但是在更新缓存方面,对于更...

Java填坑之路
07/18
0
0
使用sqlmap对某php网站进行注入实战及安全防范

使用sqlmap对某php网站进行注入实战 一般来讲一旦网站存在sql注入漏洞,通过sql注入漏洞轻者可以获取数据,严重的将获取webshell以及服务器权限,但在实际漏洞利用和测试过程中,也可能因为服...

simeon2005
06/29
0
0
分布式之数据库和缓存双写一致性方案解析

原文出处:孤独烟 引言 为什么写这篇文章? 首先,缓存由于其高并发和高性能的特性,已经在项目中被广泛使用。在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作。 但是在更新...

孤独烟
05/17
0
0
分布式数据库与缓存双写一致性方案解疑

作者介绍 孤独烟,中国平安研发工程师,目前负责规则云平台架构设计以及需求研发工作。毕业后一直从事Java开发工作,在Web开发、架构设计上有多年的实战经验。在MySQL性能优化、JVM调优、分布...

孤独烟
06/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

180.mariadb 主从复制

参考:https://blog.csdn.net/chengxuzaza/article/details/62042920 睡觉睡觉,明天写 1.效果 当主库中数据有变化的时候,从库就自动同步 2. 环境要求 至少两台 linux服务器 (教程:https...

Lucky_Me
11分钟前
0
0
erlng file id3v1 id3v1.1

%% ---%% Excerpted from "Programming Erlang",%% published by The Pragmatic Bookshelf.%% Copyrights apply to this code. It may not be used to create training material, %% ......

xueyuse0012
12分钟前
0
0
RabbitMq的安装

环境Centos6.5 32位 JDK 1.7.8 Jdk的卸载 rpm -qa|grep jdk yum –y remove 上边的安装包 JDK的安装 Rpm –ivh jdk安装包 配置环境变量 export JAVA_BIN=/usr/java/jdk1.7.0_80/bin export J......

DemonsI
16分钟前
0
0
http和https协议

HTTPS全称为Hypertext Transfer Protocol over Secure Socket Layer,中文含义为“超文本传输协议在安全加密字层”,简单来说就是加密数据传输,通俗的说就是安全连接。 HTTPS安全超文本传输...

寰宇01
22分钟前
0
0
vue内引入语音播报功能

在vue项目中引入语音播报,使用的科大讯飞语音接入, 具体思路为每次接收到语音信息后存入一个数组,然后监听这个数组,开始冲第一个索引播放,并且同时根据vuex getter 来动态删减数量 给a...

originDu
30分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部