日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
如何真正來區(qū)分一下不可重復讀和幻讀

[[215809]]

幻讀 (間隙鎖)

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

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

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

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

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

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

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

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

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

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

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

打開客戶端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. 3 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. 3 rows in set (0.00 sec) 
  18.   
  19. mysql>  

在客戶端2中開啟事務, 然后查詢數(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. 3 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. 4 rows in set (0.00 sec) 
  13.   
  14. mysql>  

在客戶端2事務中再次查詢數(shù)據(jù), 發(fā)現(xiàn)數(shù)據(jù)沒有變化(表示可以重復讀, 并且克服了幻讀), 但是在客戶端2事務中插入一條id為4的新數(shù)據(jù), 發(fā)現(xiàn)提示數(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. 3 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. 3 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>  

那么這是什么問題呢?

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


網頁名稱:如何真正來區(qū)分一下不可重復讀和幻讀
分享地址:http://www.5511xx.com/article/dpdccee.html