自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何真正來區(qū)分一下 不可重復(fù)讀和幻讀

數(shù)據(jù)庫 MySQL
雖然網(wǎng)上有不少資料提到幻讀, 但是可能表達(dá)的都不太準(zhǔn)確, 比如這樣一段對幻讀的解釋 '同樣的條件, 第一次和第二次讀出來的記錄不一樣' 在網(wǎng)絡(luò)上隨處可見, 但其實(shí)并不準(zhǔn)確, 因?yàn)?delete 其實(shí)并不是幻讀的范疇(MySQL官方文檔對 Phantom Rows 的介紹)也一點(diǎn)都沒涉及到delete)。

[[215809]]

幻讀 (間隙鎖)

1.由于很多人(當(dāng)然也包括本人), 容易搞混 不可重復(fù)讀 和 幻讀 , 這兩者確實(shí)非常相似。

  • 但 不可重復(fù)讀 的重點(diǎn)是針對 update, delete。
  • 而 幻讀 的重點(diǎn)針對的是 insert。(可以參考MySQL官方文檔對 Phantom Rows 的介紹)

2.雖然網(wǎng)上有不少資料提到幻讀, 但是可能表達(dá)的都不太準(zhǔn)確, 比如這樣一段對幻讀的解釋 '同樣的條件, ***次和第二次讀出來的記錄不一樣' 在網(wǎng)絡(luò)上隨處可見, 但其實(shí)并不準(zhǔn)確, 因?yàn)?delete 其實(shí)并不是幻讀的范疇(MySQL官方文檔對 Phantom Rows 的介紹)也一點(diǎn)都沒涉及到delete)。

3.如果手動加鎖來演示, 你便會看清他們的本質(zhì):

  • 如果 insert, 則操作被阻塞, 并且可以看到具體加的是X鎖+GAP鎖:

  • 如果 delete或者update, 則操作被阻塞, 但是可以看到具體加的只有X鎖:

可以看到, 其他事務(wù)只有在 insert 的時候, 才會加GAP鎖來防止幻讀, 所以delete/update 和 insert 是要區(qū)分開的.

不過, 后面學(xué)到mvcc的時候, 你會知道加鎖的低效性, 所以還有兩種解決方案:

使用隔離性的***隔離級別SERIALIZABLE, 但該隔離級別在實(shí)際中很少使用;

其實(shí) REPEATABLE READ 就可以防止幻讀, 《高性能MySQL》中也說了, REPEATABLE READ 理論是是不能防止幻讀的, 但是由于該隔離級別還使用了MVCC, 可以做到非鎖定一致性讀取, 所以, 只要你真的確定你明白幻讀的意思, 你在 REPEATABLE READ隔離級別下是模擬不出幻讀效果的;

至于網(wǎng)絡(luò)上如下所謂的幻讀現(xiàn)象, 本人覺得是誤導(dǎo), 剛開始本人也認(rèn)為這就是REPEATABLE-READ隔離級別無法解決幻讀的鐵證, 后來發(fā)現(xiàn)錯了, 幻讀是指兩次讀操作發(fā)現(xiàn)記錄增多導(dǎo)致的不一致, 而如下是多次insert, 雖然也是個問題, 但已經(jīng)不是 幻讀 問題了:

打開客戶端1查看隔離級別及初始數(shù)據(jù)

  1. mysql> SELECT @@SESSION.tx_isolation; 
  2. +------------------------+ 
  3. | @@SESSION.tx_isolation | 
  4. +------------------------+ 
  5. REPEATABLE-READ        | 
  6. +------------------------+ 
  7. 1 row in set (0.00 sec) 
  8.   
  9. mysql> select * from test_transaction; 
  10. +----+-----------+-----+--------+--------------------+ 
  11. | id | user_name | age | gender | desctiption        | 
  12. +----+-----------+-----+--------+--------------------+ 
  13. |  1 | 金剛狼 | 127 |      1 | 我有一雙鐵爪 | 
  14. |  2 | 鋼鐵俠 | 120 |      1 | 我有一身鐵甲 | 
  15. |  3 | 綠巨人 |   0 |      2 | 我有一身肉    | 
  16. +----+-----------+-----+--------+--------------------+ 
  17. rows in set (0.00 sec) 
  18.   
  19. mysql>  
  • 打開客戶端2查看隔離級別及初始數(shù)據(jù)
  1. mysql> SELECT @@SESSION.tx_isolation; 
  2. +------------------------+ 
  3. | @@SESSION.tx_isolation | 
  4. +------------------------+ 
  5. REPEATABLE-READ        | 
  6. +------------------------+ 
  7. 1 row in set (0.00 sec) 
  8.   
  9. mysql> select * from test_transaction; 
  10. +----+-----------+-----+--------+--------------------+ 
  11. | id | user_name | age | gender | desctiption        | 
  12. +----+-----------+-----+--------+--------------------+ 
  13. |  1 | 金剛狼 | 127 |      1 | 我有一雙鐵爪 | 
  14. |  2 | 鋼鐵俠 | 120 |      1 | 我有一身鐵甲 | 
  15. |  3 | 綠巨人 |   0 |      2 | 我有一身肉    | 
  16. +----+-----------+-----+--------+--------------------+ 
  17. rows in set (0.00 sec) 
  18.   
  19. mysql>  

在客戶端2中開啟事務(wù), 然后查詢數(shù)據(jù)

  1. mysql> begin
  2. Query OK, 0 rows affected (0.00 sec) 
  3.   
  4. mysql> select * from test_transaction; 
  5. +----+-----------+-----+--------+--------------------+ 
  6. | id | user_name | age | gender | desctiption        | 
  7. +----+-----------+-----+--------+--------------------+ 
  8. |  1 | 金剛狼 | 127 |      1 | 我有一雙鐵爪 | 
  9. |  2 | 鋼鐵俠 | 120 |      1 | 我有一身鐵甲 | 
  10. |  3 | 綠巨人 |   0 |      2 | 我有一身肉    | 
  11. +----+-----------+-----+--------+--------------------+ 
  12. rows in set (0.00 sec) 
  13.   
  14. mysql>  

在客戶端1中插入一條id為4的新數(shù)據(jù) (直接自動提交)

  1. mysql> insert into test_transaction (`id`,`user_name`,`age`,`gender`,`desctiption`) values (4, '死侍', 18, 0, 'A bad boy'); 
  2. Query OK, 1 row affected (0.00 sec) 
  3. mysql> select * from test_transaction; 
  4. +----+-----------+-----+--------+--------------------+ 
  5. | id | user_name | age | gender | desctiption        | 
  6. +----+-----------+-----+--------+--------------------+ 
  7. |  1 | 金剛狼 | 127 |      1 | 我有一雙鐵爪 | 
  8. |  2 | 鋼鐵俠 | 120 |      1 | 我有一身鐵甲 | 
  9. |  3 | 綠巨人 |   0 |      2 | 我有一身肉    | 
  10. |  4 | 死侍    |  18 |      0 | A bad boy          | 
  11. +----+-----------+-----+--------+--------------------+ 
  12. rows in set (0.00 sec) 
  13.   
  14. mysql>  

在客戶端2事務(wù)中再次查詢數(shù)據(jù), 發(fā)現(xiàn)數(shù)據(jù)沒有變化(表示可以重復(fù)讀, 并且克服了幻讀), 但是在客戶端2事務(wù)中插入一條id為4的新數(shù)據(jù), 發(fā)現(xiàn)提示數(shù)據(jù)已經(jīng)存在, 注意, 雖然爆出問題來了, 但不是 幻讀 范疇

  1. mysql> begin
  2. Query OK, 0 rows affected (0.00 sec) 
  3.   
  4. mysql> select * from test_transaction; 
  5. +----+-----------+-----+--------+--------------------+ 
  6. | id | user_name | age | gender | desctiption        | 
  7. +----+-----------+-----+--------+--------------------+ 
  8. |  1 | 金剛狼 | 127 |      1 | 我有一雙鐵爪 | 
  9. |  2 | 鋼鐵俠 | 120 |      1 | 我有一身鐵甲 | 
  10. |  3 | 綠巨人 |   0 |      2 | 我有一身肉    | 
  11. +----+-----------+-----+--------+--------------------+ 
  12. rows in set (0.00 sec) 
  13.  
  14. mysql> select * from test_transaction; 
  15. +----+-----------+-----+--------+--------------------+ 
  16. | id | user_name | age | gender | desctiption        | 
  17. +----+-----------+-----+--------+--------------------+ 
  18. |  1 | 金剛狼 | 127 |      1 | 我有一雙鐵爪 | 
  19. |  2 | 鋼鐵俠 | 120 |      1 | 我有一身鐵甲 | 
  20. |  3 | 綠巨人 |   0 |      2 | 我有一身肉    | 
  21. +----+-----------+-----+--------+--------------------+ 
  22. rows in set (0.00 sec) 
  23.  
  24. mysql> insert into test_transaction (`id`,`user_name`,`age`,`gender`,`desctiption`) values (4, '死侍', 18, 0, 'A bad boy'); 
  25. 1062 - Duplicate entry '4' for key 'PRIMARY' 
  26. mysql>  

那么這是什么問題呢?

個人認(rèn)為, 如果你的表中真的會出現(xiàn)兩條完全相同的記錄, 考慮一下, 最起碼的表規(guī)范(第二范式)是否先滿足一下?

責(zé)任編輯:武曉燕 來源: Segmentfault
相關(guān)推薦

2022-04-27 07:32:02

臟讀幻讀不可重復(fù)讀

2024-04-24 08:26:35

事務(wù)數(shù)據(jù)InnoDB

2024-04-19 08:18:47

MySQLSQL隔離

2019-03-21 09:06:00

數(shù)據(jù)庫復(fù)讀幻讀

2022-01-03 07:18:05

臟讀幻讀 MySQL

2023-11-01 14:13:00

MySQL事務(wù)隔離級別

2025-02-26 10:40:44

數(shù)據(jù)庫并發(fā)幻讀

2022-06-29 11:01:05

MySQL事務(wù)隔離級別

2021-08-02 09:01:05

MySQL 多版本并發(fā)數(shù)據(jù)庫

2023-02-02 07:06:10

2023-10-26 00:41:46

臟讀數(shù)據(jù)幻讀

2024-05-13 11:46:33

MySQL數(shù)據(jù)庫

2019-05-28 13:50:27

MySQL幻讀數(shù)據(jù)庫

2024-07-16 08:19:46

MySQL數(shù)據(jù)InnoDB

2021-04-20 19:21:50

臟讀MySQL幻讀

2023-12-26 08:08:02

Spring事務(wù)MySQL

2019-12-24 14:50:01

MySQL可重復(fù)讀數(shù)據(jù)庫

2021-09-07 10:33:42

MySQL事務(wù)隔離性

2024-03-11 00:00:00

mysqlInnoDB幻讀

2022-09-21 09:00:10

MySQL幻讀隔離級別
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號