文档章节

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

Eric_chan
 Eric_chan
发布于 2015/05/05 18:17
字数 1171
阅读 24
收藏 0
点赞 0
评论 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 ⋅ 0

使用sqlmap对某php网站进行注入实战及安全防范

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

simeon2005 ⋅ 05/30 ⋅ 0

分布式之数据库和缓存双写一致性方案解析

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

孤独烟 ⋅ 05/17 ⋅ 0

分布式数据库与缓存双写一致性方案解疑

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

孤独烟 ⋅ 06/01 ⋅ 0

mysql主从同步搭建和故障排除

主从同步的定义: 是存储数据的一种结构模式。 主:被客户端访问的数据库服务器就是主库服务器master 从:连接主库服务器,自动同步主库的所有数据到本机slave 1、什么是mysql主从同步? 当m...

Morning晨丿 ⋅ 06/01 ⋅ 0

mysql 5.6的半同步复制和官方提供的mysqlfailover高可用解决方案

mysql 5.6开始,提供了GTID形式的复制,这会极大程度上简单数据库管理的工作量。 在以前版本中,我们搭建从库时,必须指定要复制的二进制文件和位置(设置不当,容易造成同步失败或数据一致性...

月影又无痕 ⋅ 2013/12/18 ⋅ 0

【转】PDO函数属性详解

PHP官方文档关于PDO的翻译已经部分完成了,可以直接去查看官方文档了 http://php.net/manual/zh/book.pdo.php PDO是一个“数据库访问抽象层”,作用是统一各种数据库的访问接口,与mysql和m...

狗头666 ⋅ 2012/02/15 ⋅ 0

PHP 多线程详解

PHP 高级编程之多线程 http://netkiller.github.io/journal/php.thread.html 2015-10-26 目录 1. 多线程环境安装 2. Thread 3. Worker 与 Stackable 4. 互斥锁 5. 线程同步 6. 线程池 7. 多线......

neo-chen ⋅ 2015/10/26 ⋅ 0

mysql双主配置及其注意事项

mysql双主配置及其注意事项 主库配置 从库配置 主键冲突 多主和主从有一点区别:因为在多主中都有对服务器有写的权限,所以会造成主键冲突。从而导致同步失败。所以需要保证自增长的数据不同...

jay_zhao ⋅ 03/28 ⋅ 0

MySQL 同步和主从设置

关于 MySQL 主从复制的配置,网络上可以搜出成筐的文章来,但下面这篇写得很清晰、简洁,值得推荐: 以下文章内容转自阿权的书房。 设置Mysql的主从设置很重要,有如下几点用处: 1 做备份机...

红薯 ⋅ 2010/08/11 ⋅ 2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

思路分析 如何通过反射 给 bean entity 对象 的List 集合属性赋值?

其实 这块 大家 去 看 springmvc 源码 肯定可以找到实现办法。 因为 spirngmvc 的方法 是可以 为 对象 参数里面的 list 属性赋值的。 我也没有看 具体的 mvc 源码实现,我这里只是 写一个 简...

之渊 ⋅ 33分钟前 ⋅ 0

vim使用手册--配对括号的查找

1、把光标放在标记有(、[或{处。 2、按%字符 3、此时光标的位置应当在配对的括号处 4、再次按%就可以跳回配对的第一个括号处。

dragon_tech ⋅ 36分钟前 ⋅ 0

c++ 、object-c printf,%02X和%x有什么区别 ?

%x即按十六进制输出,英文字母小写,右对齐。 %02X有以下变化:英文字母变大写,如果输出字符不足两位的,输出两位宽度,右对齐,空的一位补0。超过两位的,全部输出。 如果不用 %02x 会出现...

yizhichao ⋅ 41分钟前 ⋅ 0

Spring源码解析(七)——实例创建(中)

前言 上一节讲到了,Spring 会根据实例的作用域执行不同的创建逻辑,分别是 Singleton、Prototype、其他 Scope,其中 Singleton 会调用 getSingleton 从缓存中获取,缓存中没有才会创建实例;...

MarvelCode ⋅ 42分钟前 ⋅ 0

Thrift RPC实战(六) spring集成thrift

1.服务端设置 对泛型Thrift Service的支持, 通过采用spring配置以及反射的方式来实现.对于一个服务提供者来说,需要提供端口,接口以及接口实现类,因此在接口中spring配置文件中配置如下 <!...

lemonLove ⋅ 44分钟前 ⋅ 0

oracle11g自动分区使用

为什么使用自动分区? 在oracle11g之前,oracle是不支持自动分区功能的,这就可能导致我们系统在运行一段时间之后,就需要看看分区是否创建或者写触发器进行创建分区,否则就会导致数据无法入...

strict_nerd ⋅ 55分钟前 ⋅ 0

Spring mvc ViewResolver视图解析器实现机制

概要 我们在controller里面经常这样return一个ModelAndView。 return new ModelAndView("userList", "users", userList); DispatcherServlet 靠 ViewResolver 把 userList 解析为 /WEB-INF......

轨迹_ ⋅ 今天 ⋅ 0

策略模式

1.策略模式 策略模式是同一个行为的不同处理办法。策略模式和简单工厂模式的区别:1.策略模式主要是方法的执行方式,工厂模式要获取的对象。两者的侧重点不同。 ...

Cobbage ⋅ 今天 ⋅ 0

行政区划代码转为字典形式

原数据为: http://www.mca.gov.cn/article/sj/xzqh/2018/201804-12/201804-06041553.html 手动替换了一下格式,并使用下面的代码处理. # 输入格式s = """110000:北京市110101:东城区1101...

漫步海边小路 ⋅ 今天 ⋅ 0

android apk 签名

创建key,需要用到keytool.exe (位于C:\Program Files\Java\jdk1.6.0_10\bin目录下),使用产生的key对apk签名用到的是jarsigner.exe (位于C:\Program Files\Java\jdk1.6.0_10\bin目录下),把...

国仔饼 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部