今天很忙,原本想存成草稿有空在编辑的。结果一不当心发布了,因此只能先写完了。 html
先描述下背景,一个提问的问题 mysql
之前我认为,只要是update的where条件能够找到数据的,那么返回的影响行数必然是大于0的。
写了一个SQL: UPDATE tss_view_template SET name='默认风格' where id=1; 结果返回影响行数是0,可是SQL变成这样: UPDATE tss_view_template SET name='默认风格',gmt_create=now() where id=1; 结果返回影响行数是1 难道说这条update的执行以前,会先比对你要更新的字段,若是是同样的,就不算是更新 仍是说这个是MySQL的特性
把这个问题简单的概括下就是,updae语句若是不实际改变数据,那么会不会在底层作操做? sql
因而在本地作了一下测试 oracle
mysql> update test set a=1 where b=2; Query OK, 0 rows affected Rows matched: 1 Changed: 0 Warnings: 0 mysql> select row_count(); +-------------+ | row_count() | +-------------+ | 0 | +-------------+ 1 row in set mysql> update test set a=2 where b=2; Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0 mysql> select row_count(); +-------------+ | row_count() | +-------------+ | 1 | +-------------+ 1 row in set mysql> select version(); +-----------+ | version() | +-----------+ | 5.5.15 | +-----------+ 1 row in set个人测试环境是mysql5.5.15,其中row mathc和row change倒是和问题中的描述同样。咱们主要关注一下change这个数列
另外我再实验中使用了select row_count这个函数,能够看到这个值和change是一致的。 函数
关于row_count这个函数,咱们能够参考一下mysql的文档 ,mysql的官方文档上是这么写的“For UPDATE statements, the affected-rows value by default is the number of rows actually changed. If you specify the CLIENT_FOUND_ROWS flag to mysql_real_connect() when connecting to mysqld, the affected-rows value is the number of rows “found”; that is, matched by the WHERE clause.” 也就是说是默认状况下是actually影响的值,可是在mysql启动的时候改变下CLIENT_FOUND_ROWS这个值的话就是“发现的值”而不是“改变的值”。下面是参考文档的原文 测试
http://dev.mysql.com/doc/refman/5.5/en//information-functions.html#function_row-count spa
另外关于row_count这个问题 有人在stackoverflow中提过类似的问题。意思是这个好像和mysql的版本有关,见下面的链接 code
http://stackoverflow.com/questions/12673925/row-count-returns-0-after-insert-or-update orm
可是我特地在5.1上作了这个实验,并无复现这个问题。下面是我在本地的实验截图 htm
mysql到底是怎么作的呢?
有两个值。 Rows matched和Changed 前者表示匹配的行数,后者表示改变的行数。 若是update语句没有对数据作出修改,则changed为0,若是有一行匹配的记录的话,Rows matched为1
在进入Innodb层时,会判断是否作出修改,ha_innobase::update_row->calc_row_difference 不过从代码的逻辑来看,即便须要更新的字段数为0,仍是会跑到更新记录的逻辑,只是没有修改任何数据而已
例如 mysql> create table x1 (a int, b int); Query OK, 0 rows affected (0.00 sec)
mysql> insert into x1 values (1,2),(2,3); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0
mysql> update x1 set a=1 where b =2; Query OK, 0 rows affected (0.00 sec) Rows matched: 1 Changed: 0 Warnings: 0
mysql> update x1 set a=12 where b =2; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0
能够参考这个mysql的文档
http://blogs.innodb.com/wp/2010/09/mysql-5-5-innodb-change-buffering/
mysql是这样的,那么oracle对于update相同的行时又是怎么作的呢?
这里我就不作实验了,参考一个网上的博客,获得的结论就是oracle在处理相同行的时候会是会作更新操做的。
总结一下,msyql在update相同的行的时候是不会作change操做的,而oracle是会记录这个行的。