背景

本文主要測試MySQL執行update語句時,針對與原數據(即未修改)相同的update語句會在MySQL內部重新執行嗎?

測試環境

  • MySQL5.7.25
  • Centos 7.4

binlog_format為ROW

參數

root@localhost : (none) 04:53:15> show variables like binlog_row_image;
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| binlog_row_image | FULL |
+------------------+-------+
1 row in set (0.00 sec)

root@localhost : (none) 04:53:49> show variables like binlog_format;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)

root@localhost : test 05:15:14> show variables like transaction_isolation;
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.00 sec)

測試步驟

session1

root@localhost : test 04:49:48> begin;
Query OK, 0 rows affected (0.00 sec)

root@localhost : test 04:49:52> select * from test where id =1;
+----+------+------+------+
| id | sid | mid | name |
+----+------+------+------+
| 1 | 999 | 871 | NW |
+----+------+------+------+
1 row in set (0.00 sec)

root@localhost : (none) 04:54:03> show engine innodb statusGshow master statusG
...
---
LOG
---
Log sequence number 12090390
Log flushed up to 12090390
Pages flushed up to 12090390
Last checkpoint at 12090381
0 pending log flushes, 0 pending chkp writes
33 log i/os done, 0.00 log i/os/second

*************************** 1. row ***************************
File: mysql-bin.000001
Position: 154
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)

session2

root@localhost : test 04:47:45> update test set sid=55 where id =1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

root@localhost : (none) 04:54:03> show engine innodb statusGshow master statusG
...
---
LOG
---
Log sequence number 12091486
Log flushed up to 12091486
Pages flushed up to 12091486
Last checkpoint at 12091477
0 pending log flushes, 0 pending chkp writes
39 log i/os done, 0.00 log i/os/second

*************************** 1. row ***************************
File: mysql-bin.000001
Position: 500
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: 8392d215-4928-11e9-a751-0242ac110002:1
1 row in set (0.00 sec)

session1

root@localhost : test 04:49:57> update test set sid=55 where id =1;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0

root@localhost : (none) 04:54:03> show engine innodb statusGshow master statusG
...
---
LOG
---
Log sequence number 12091486
Log flushed up to 12091486
Pages flushed up to 12091486
Last checkpoint at 12091477
0 pending log flushes, 0 pending chkp writes
39 log i/os done, 0.00 log i/os/second

*************************** 1. row ***************************
File: mysql-bin.000001
Position: 500
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: 8392d215-4928-11e9-a751-0242ac110002:1
1 row in set (0.00 sec)

root@localhost : test 04:52:05> select * from test where id =1;
+----+------+------+------+
| id | sid | mid | name |
+----+------+------+------+
| 1 | 999 | 871 | NW |
+----+------+------+------+
1 row in set (0.00 sec)

root@localhost : test 04:52:42> commit;
Query OK, 0 rows affected (0.00 sec)

root@localhost : test 04:52:52> select * from test where id =1;
+----+------+------+------+
| id | sid | mid | name |
+----+------+------+------+
| 1 | 55 | 871 | NW |
+----+------+------+------+
1 row in set (0.00 sec)

總結

在binlog_format=row和binlog_row_image=FULL時,由於MySQL 需要在 binlog 裡面記錄所有的欄位,所以在讀數據的時候就會把所有數據都讀出來,那麼重複數據的update不會執行。即MySQL 調用了 InnoDB 引擎提供的「修改為 (1,55)」這個介面,但是引擎發現值與原來相同,不更新,直接返回

binlog_format為STATEMENT

參數

root@localhost : (none) 04:53:15> show variables like binlog_row_image;
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| binlog_row_image | FULL |
+------------------+-------+
1 row in set (0.00 sec)

root@localhost : (none) 05:16:08> show variables like binlog_format;
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
1 row in set (0.00 sec)

root@localhost : test 05:15:14> show variables like transaction_isolation;
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.00 sec)

測試步驟

session1

root@localhost : test 05:16:42> begin;
Query OK, 0 rows affected (0.00 sec)

root@localhost : test 05:16:44> select * from test where id =1;
+----+------+------+------+
| id | sid | mid | name |
+----+------+------+------+
| 1 | 111 | 871 | NW |
+----+------+------+------+
1 row in set (0.00 sec)

root@localhost : (none) 05:16:51> show engine innodb statusGshow master statusG
...
---
LOG
---
Log sequence number 12092582
Log flushed up to 12092582
Pages flushed up to 12092582
Last checkpoint at 12092573
0 pending log flushes, 0 pending chkp writes
45 log i/os done, 0.00 log i/os/second

*************************** 1. row ***************************
File: mysql-bin.000001
Position: 154
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)

session2

root@localhost : test 05:18:30> update test set sid=999 where id =1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

root@localhost : (none) 05:18:47> show engine innodb statusGshow master statusG
...
---
LOG
---
Log sequence number 12093678
Log flushed up to 12093678
Pages flushed up to 12093678
Last checkpoint at 12093669
0 pending log flushes, 0 pending chkp writes
51 log i/os done, 0.14 log i/os/second

*************************** 1. row ***************************
File: mysql-bin.000001
Position: 438
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: 8392d215-4928-11e9-a751-0242ac110002:1
1 row in set (0.00 sec)

session1

root@localhost : test 05:16:47> update test set sid=999 where id =1;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0

root@localhost : (none) 05:20:03> show engine innodb statusGshow master statusG
...
---
LOG
---
Log sequence number 12094504
Log flushed up to 12094504
Pages flushed up to 12094504
Last checkpoint at 12094495
0 pending log flushes, 0 pending chkp writes
56 log i/os done, 0.00 log i/os/second

*************************** 1. row ***************************
File: mysql-bin.000001
Position: 438
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: 8392d215-4928-11e9-a751-0242ac110002:1
1 row in set (0.00 sec)

root@localhost : test 05:19:33> select * from test where id =1;
+----+------+------+------+
| id | sid | mid | name |
+----+------+------+------+
| 1 | 999 | 871 | NW |
+----+------+------+------+
1 row in set (0.00 sec)

root@localhost : test 05:20:44> commit;
Query OK, 0 rows affected (0.01 sec)

root@localhost : test 05:20:57> select * from test where id =1;
+----+------+------+------+
| id | sid | mid | name |
+----+------+------+------+
| 1 | 999 | 871 | NW |
+----+------+------+------+
1 row in set (0.00 sec)

總結

在binlog_format=statement和binlog_row_image=FULL時,InnoDB內部認真執行了update語句,即「把這個值修改成 (1,999)「這個操作,該加鎖的加鎖,該更新的更新。

一站式開發者服務,海量學習資源0元起!

阿里熱門開源項目、機器學習乾貨、開發者課程/工具、小微項目、移動研發等海量資源;更有開發者福利Kindle、技術圖書幸運抽獎,100%中--》aliyun.com/acts/product

本文作者:powdba

原文鏈接

更多技術乾貨敬請關注云棲社區知乎機構號:阿里云云棲社區 - 知乎

本文為雲棲社區原創內容,未經允許不得轉載。


推薦閱讀:
相關文章