byrcc 发表于 2012-08-15 13:44

【讨论中】【更新】求教:binlog中字段值是十六进制

本帖最后由 byrcc 于 2012-09-07 18:32 编辑

前些时间很忙,没有继续分析这个问题。今天再研究了一下,有些眉头了,基本定位到prepare statement的问题,并且可以重现,脚本附后面。在这里有个类似的问题http://bugs.mysql.com/bug.php?id=54791,不过粗看一下还是没发现问题根源和解决办法。求各位大牛帮分析分析!
重现条件:1,表gbk编码。2,使用prepare方式插入数据。
我在5.0.77-log和5.1.61-log版本的mysql上都测试都有这问题,php版本5.1.6
插入数据可以成功,并在表中能查到数据,值都正确,但是使用mysqlbinlog查看到的sql中的数值是十六进制的,而general query log也显示是十六进制的,如下
mysqlbinlog查看结果:
insert into tbl_test_pdo values(0x30,0x313030373736363032,0xB2E2)
general log:Time               Id Command    Argument
120907 18:24:20   1 Connect   root@127.0.0.1 on cc
                  1 Query   set names gbk
                  1 Prepare   insert into tbl_test_pdo values(?,?,?)
                  1 Execute   insert into tbl_test_pdo values(0x30,0x313030373736363032,0xB2E2)
                  1 Close stmt我测试使用的脚本
建表:CREATE TABLE `tbl_test_pdo` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`num` decimal(18,0) DEFAULT NULL,
`dsc` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=56 DEFAULT CHARSET=gbkphp脚本:$dbms='mysql';
$host='127.0.0.1';
$dbname='test';
$dbuser='root';
$dbpass='pass';
$dsn="$dbms:host=$host;dbname=$dbname";
try {
        $dbh = new PDO($dsn, $dbuser, $dbpass);
        $sql2 = "insert into tbl_test_pdo values(:_1,:_2,:_3)";
        $dbh->exec('set names gbk');
        $stmt = $dbh->prepare($sql2,array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
        $rlt = $stmt->execute(array(':_1'=>0,':_2'=>100776602,':_3'=>'测'));
} catch (PDOException $e) {die ("Error!: " . $e->getMessage()); }===================上次发贴内容=====================
新手求教大家一个问题
mysql版本:5.1.61-log
使用这个版本自带mysqlbinlog查看一个binlog文件,发现有下面的sql。它的特点是,values列表的值全是十六进制的,开发反应也没有直接使用十六进制操作数据库。为啥查看出来的binlog结果是这样的呢?
表的id定义为decimal(18,0) primary key,而这个sql中的id值0x313030373736383436转成十进制后,已经超过decimal(18,0)的范围。当前mysql的sql_mode为默认设置。这条数据,依据开发的log,id的值大概在100776703这个值大小。而100776703这个id在表中也能够查到那条数据。
这问题导致的结果是,在从库上,这个表的更新报错了,错误描述是tbl_xxxxxxxxxx这个表id主键冲突,冲突的值是999999999999999999,这个值恰好是十六进制id值0x313030373736383436截断到精度decimal(18,0)后的值。

不知道大家是否遇到过同样的问题?

insert into tbl_xxxxxxxxxx (id,version,createtime,updatetime,...在此省略部分字段列表...) values (0x313030373736383436,0x31,0x323031322D30382D31342031363A31313A3132,0x323031322D30382D31342031363A31313A3132,"","",0x313932307831323030,"","","","",0x736F676F752E636F6D,0xBAA3D4F4CDF5382E6A7067,0x373532,"","","","","","","",0x2F75706C6F6164496D6167652F323031322F30382F31342F313334343933313837325F352E6A7067,0x2F75706C6F6164496D6167652F323031322F30382F31342F313334343933313837325F352E6A70675F73,0x31,0x33,0x2D31,0x3530,0x30,0x2D31,0x2D31,0x30,0x31,"")

cenalulu 发表于 2012-08-15 16:46

mysqlbinlog 用什么参数查看的?

cenalulu 发表于 2012-08-15 16:46

mysqlbinlog 用什么参数查看的?

byrcc 发表于 2012-08-15 17:33

就直接是mysqlbinlog logfile_name,并且在slave库上,报错时,show slave status 看到的错误信息中sql里的值也是十六进制的,同样在从库的errorlog中显示得结果也如此
回复 3# cenalulu


   

cenalulu 发表于 2012-08-15 17:34

master 上的binlog有这个问题么?

PS:这个event 是row format 还是statement format的?

byrcc 发表于 2012-08-15 17:45

本帖最后由 byrcc 于 2012-08-15 17:46 编辑

回复 5# cenalulu


这个sql是在master上的binlog中看到的。

mysql 5.1.61版本,刚从5.0版本升级完成,没有修改mysql的默认复制模式,所以应该是statement format,不过不知道跟升级是否有关。只是升级之前从库一直打开着slave-skip-errors=1062,升级以后特意把它关闭了。

ps:开发说这个表操作有点特殊,使用了pdo连接,执行sql前运行了PDO:: perpare。这东西没见过,也没研究,但应该跟它无关吧

cenalulu 发表于 2012-08-15 18:46

如果是statment format的话,SQL 应该是原样保存的。
应该不是mysql级别的问题。
看看程序过来的query是不是就是十六进制模式的。
general log 或者tcpdump看下

byrcc 发表于 2012-08-16 19:59

搜到这个帖子,也遇到了同样的问题。不过我还在跟开发沟通
http://www.itpub.net/forum.php?mod=viewthread&action=printable&tid=1402633

rucypli 发表于 2012-08-16 21:23

这个还真没遇到过   不过主键id竟然不是自增键啊

rucypli 发表于 2012-08-16 21:24

不过可以肯定这个insert语句肯定是开发那边的问题
页: [1] 2
查看完整版本: 【讨论中】【更新】求教:binlog中字段值是十六进制