免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7864 | 回复: 6
打印 上一主题 下一主题

一个数据库错误 Statement may not be safe to log in statement format [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-16 18:17 |只看该作者 |倒序浏览
php代码
        $db     = new mysqli('localhost', '*****', '*****', '*****');
        $name   = $this->_context->phone_name;
        $yue            = (float)$this->_context->phone_yue;
                $id             = (int)$this->_context->id;
                $class_id       = (int)$this->_context->class_id;
        if( is_numeric( $name ) )
            $name = '';
        else{
            $name = strlen($name) > 12 ? substr($$name, 0, 12).'...' : $name;
        }
        $phone_yue = (float)$this->_context->phone_yue;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if($class_id <0 && $class > 10){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}elseif($class_id != 3)   //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$sql = "update phone set class_id={$class_id}, phone_name='{$name}', phone_yue='{$yue}', updated=".CURRENT_TIMESTAMP." where id={$id}";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$db->query($sql);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}else{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$db->query("call return_false({$id})");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}



mysql错误日志
100116  3:11:33 [Warning] Statement may not be safe to log in statement format. Statement: UPDATE `chengfeng`.`phone` SET `class_id` = '2' WHERE `phone`.`id` = 4330268 LIMIT 1
100116  3:11:38 [Warning] Statement may not be safe to log in statement format. Statement: UPDATE `chengfeng`.`phone` SET `class_id` = '2' WHERE `phone`.`id` = 4330183 LIMIT 1

正常情况下 表phone的字段class_id为2或者是3
当出现上面的错误日志时 class_id的值都变成0了

出现的频率为,一天4万个update语句出现次数约为3~10之间,
另外我感觉,这个出现的机率和网速有关,如果网速比较理想那么就少,甚至没有,如果网速慢,就会多一些

求助

[ 本帖最后由 风远尘 于 2010-1-16 18:18 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2010-01-16 23:02 |只看该作者

是mysql的一个bug

any UPDATE statement with LIMIT clause is considered unsafe  since the order of the rows affected is not defined

http://bugs.mysql.com/bug.php?id=42415

重现的步骤

How to repeat:
mysql> CREATE TABLE t (a INT, b INT, c INT, PRIMARY KEY(a,b));
Query OK, 0 rows affected (0.02 sec)

mysql> CREATE SQL SECURITY INVOKER VIEW v (x,y) AS SELECT a, b FROM t;
Query OK, 0 rows affected (0.00 sec)

mysql> UPDATE v SET x=x+1 ORDER BY y,x LIMIT 1;
Query OK, 0 rows affected, 1 warning (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0

mysql> show warnings;
+---------+------+---------------------------------------------------+
| Level   | Code | Message                                           |
+---------+------+---------------------------------------------------+
| Warning | 1592 | Statement is not safe to log in statement format. |
+---------+------+---------------------------------------------------+
1 row in set (0.00 sec)


MySQL 5.1.36 之后的版本就解决了这个问题 ,使用mysql 的row-based来进行复制

论坛徽章:
0
3 [报告]
发表于 2010-01-17 11:34 |只看该作者
我早上试了下上面的做法,发现没法重现这个警告,找了其他资料,供你参考下

1. 你的mysql版本是啥? 要提供版本号才更容易定位
2.检查你的binlog_format 的设置是否为statement,如果改成mixed应该就没警告了
3.你的update语句都带了limit 1 ,有可能导致在从库和master库更新的记录不一致,所以提示你不安全

论坛徽章:
0
4 [报告]
发表于 2010-01-17 13:04 |只看该作者
这个Bug差不多有一年了,不知道LZ现在用的那个版本的MySQL?

论坛徽章:
0
5 [报告]
发表于 2010-01-17 13:13 |只看该作者
数据库版本 5.1.37-1ubuntu5-log

这是我的数据库版本,

如您所示,
2.检查你的binlog_format 的设置是否为statement,如果改成mixed应该就没警告了
binlog format我也改成过mixed,
依然如此,变成另外一个警告了。具体的waring我没有记下来

论坛徽章:
0
6 [报告]
发表于 2010-01-17 13:17 |只看该作者
3.你的update语句都带了limit 1 ,有可能导致在从库和master库更新的记录不一致,所以提示你不安全

我自己写的update语句并没有带limit 1的,不知道怎么回事,我原来是框架自动生成的sql,我怕有带limit,后来这个地方我就自己写了sql,如下所示
$sql = "update phone set class_id={$class_id}, phone_name='{$name}', phone_yue='{$yue}', updated=".CURRENT_TIMESTAMP." where id={$id}";

没有limit的。 我也认为是数据库版本问题,最近20多天的事情,依稀就是数据库升级后出现的问题

论坛徽章:
0
7 [报告]
发表于 2010-01-17 13:20 |只看该作者
MySQL 5.1.36 之后的版本就解决了这个问题 ,使用mysql 的row-based来进行复制

这点我不太理解 使用row-based来复制是什么意思?

我服务器是运行了主从复制的,就是最普通的那种,全数据库复制
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP