今天很忙,原本想存成草稿有空在編輯的。結果一不當心發佈了,因此只能先寫完了。 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是會記錄這個行的。