前段时间给pdo设置了下emulate_prepare属性,引发了这次的血案。在这记录下事情的经过,没准大家能避免同样的错误。

先说以下环境。php 5.2.5,mysql 5.0.81,服务器使用的GBK编码。

起因

首先是看到一个报错信息,说是sql语句的syntax error。这里给一个能重现的例子。报错的位置就是在红框的位置。

排查

从上面看,看不出语法错误。然而GBK编码的“玕”字后一个字节是0x5c,跟“\”一样。看到这,是不是就觉得这可能会有问题?但是,我记得我们是使用了pdo的prepare这种方式的(上面sql语句中我使用实际的值代替了?占位符),即使这个汉子特殊,也不会报语法错误才对。于是我翻了翻代码,发现,果然没有显示的设置PDO::ATTR_EMULATE_PREPARES属性的值。而默认是设置为true的(从字面意思就能理解,模拟prepare,不是真正意义上的prepare执行方式)。

使用tcpdump抓包,wireshark查看,确定了一下,发现果然是上面这样。

抓包的结果,

0xab5c是汉字玕的GBK编码。这里看到的是,pdo模拟处理后,多加了一个'\',而在这之前,已经告诉mysql server,客户端使用的是GBK编码(set names gbk),mysql server按着GBK字符集处理sql语句,多出来的转义符号,就造成了sql语句的语法错误。(后来查资料确认,这是pdo在处理多字符时候的一个bug,好像在php5.3.6,之后版本通过dsn里面设置charset可以解决,我没去确认从哪个版本开始起作用的,但是5.4是可以起作用的。)

处理

既然pdo模拟prepare有这个问题,而真正意义的prepare既没有这个问题,又在防止sql注入上更胜一筹,那我就直接使用mysql提供的prepare执行方式就好了。所以,设置PDO::ATTR_EMULATE_PREPARES为false。测试发现,果然插入正常了。其他一切数据库操作貌似都正常。

惨啊

在我解决完问题挺高兴的时候,发现问题了。数据库主从同步出问题了。后来定位问题发现,mysql 的binlog里面sql语句里面的数据全都是转换到了ascii码的表示,例如 insert test (`id`) values(1),在binlog里面是insert test(`id`) values(0x31)。此时也才了解到mysql5.0不支持row同步方式,只支持语句的同步方式。binlog异常参见这篇文章http://backend.blog.163.com/blog/static/20229412620133274030845

总结

编程不容易,说多了都是泪。。努力,多学学吧。。

转载于:https://my.oschina.net/u/437615/blog/369481

PDO::ATTR_EMULATE_PREPARES属性设置为false引发的血案相关推荐

  1. 要重定向 IO 流,Process 对象必须将 UseShellExecute 属性设置为 False。

    Process  p1= new Process(); p1.StartInfo.UseShellExecute = false;

  2. Process对象必须将UseShellExecute属性设置为False才能使用环境变量解决办法

    加下面两行 proc.StartInfo.UseShellExecute = false; proc.StartInfo.CreateNoWindow = true; The reason being ...

  3. c# WinForm开发 DataGridView控件的各种操作总结(单元格操作,属性设置)

    一.单元格内容的操作 *****// 取得当前单元格内容 Console.WriteLine(DataGridView1.CurrentCell.Value); // 取得当前单元格的列 Index ...

  4. Gridview利用DataFormatString属性设置数据格式

    首 先把Gridview的AutoGenerateColumns属性设为False(默认是False),DataField选择相应的字段,特别需要注 意的是要把需要设置的字段的HtmlEncode属性 ...

  5. ListView部分样式属性设置

    在硬编码中: ListView lv= getListView(); lv.setDivider(new ColorDrawable(Color.GREEN));//用这个设置颜色 lv.setDiv ...

  6. asp.net页面的AutoEventWireup=true属性设置

    我们进行asp.net Web开发时,我们会习惯性的在后台的Page_Load()方法中通过IsPostBack属性的判断加载数据.那么,问题来了,你是如何知道页面加载的时候会执行Page_Load( ...

  7. asp.net页面的AutoEventWireup=“true“属性设置

    微软通过AutoEventWireup属性已经帮我们进行了事件与页面的隐式关联.这些特定名称包括:Page_Init, Page_Load, Page_DataBind, Page_PreRender ...

  8. mysql 禁用ssl连接_MySQL建立SSL连接问题,设置useSSL=false显式禁用SSL,或者设置useSSL=true...

    You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide tr ...

  9. php pdo attr_emulate_prepares,PDO操作,设置了ATTR_EMULATE_PREPARES属性为false后发现还是在本地模拟prepare...

    PDO操作,设置了ATTR_EMULATE_PREPARES属性为false后发现还是在本地模拟prepare //连接数据库部分 try{ $dbh = new PDO('mysql:dbname= ...

最新文章

  1. 啊里大鱼短信发送API
  2. 一道有意思的数据库题
  3. Java中String 和StringBuffer的区别
  4. python查询斐波那契数列通项公式_分享一个神奇的操作系统——斐波那契+MACD,每一波都有20%以上的收益!...
  5. 调用某个按钮事件_Event 对象之事件句柄 (Event Handlers)
  6. HDU - 1495 - 非常可乐
  7. 【英语学习】【Level 07】U06 First Time L6 Not your typical experience
  8. 外媒:苹果首款AR/VR设备需与iPhone绑定使用,最早明年发布
  9. java的string访问某个元素_架构师必懂的——RBAC基于角色的访问权限设计
  10. 关于MATLAB处理大数据坐标文件
  11. 内存颗粒和闪存颗粒的区别_国产闪存颗粒终于熬出头 紫光存储S100固态硬盘评测...
  12. javaJavaScript DOM
  13. 第三十四期:游戏开发中常见的10种编程语言
  14. php对接抖音快手小红书短视频去水印接口的代码
  15. mac系统Airtest环境安装教程
  16. 申宝证券-A股三大指数集体高开
  17. Java类和对象之对象组合之求圆柱体积
  18. 2018年,Facebook没倒闭是个奇迹
  19. 【论文阅读】水下机器人控制视觉伺服部分
  20. echart图表-刷新界面.初始化时默认显示hover提示内容

热门文章

  1. php取名字算法,JavaScript排序算法之希尔排序的2个实例_基础知识
  2. 资本扎堆?自动驾驶“梦幻开局”
  3. 李宏毅2020机器学习课程笔记(二)
  4. DB2 OLAP函数的使用
  5. 国产芯片替代ST很容易,航顺HK32F103RET6替代STM32F103RET6,航顺芯片,航顺MCU
  6. mysql 单表子查询语句_MySQL基本SQL查询语句:多表查询和子查询示例
  7. Java Spring Bean的生命周期 三级缓存
  8. 中国五金门控发展情况 (zz)
  9. 【初学者必看】图像处理入门,二值图像形态学(binary morphology)^_^
  10. asio(一)、同步定时器