国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > MySQL > 正文

mysql鎖機制的理念是什么

2024-07-24 12:33:16
字體:
來源:轉載
供稿:網友
  本文小編為大家詳細介紹“mysql鎖機制的概念是什么”,內容詳細,步驟清晰,細節處理妥當,希望這篇“mysql鎖機制的概念是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
 
  Mysql鎖:
 
  在多線程當中如果想保證數據的準確性是如何實現的呢?沒錯,通過同步實現。同步就相當于是加鎖。加了鎖以后有什么好處呢?當一個線程真正在操作數據的時候,其他線程只能等待。當一個線程執行完畢后,釋放鎖。其他線程才能進行操作!
 
  那么我們的MySQL數據庫中的鎖的功能也是類似的,處理事務的隔離性中,可能會出現臟讀、不可重復讀、幻讀的問題,所以,鎖的作用也可以解決這些問題!
 
  在數據庫中,數據是一種供許多用戶共享訪問的資源,如何保證數據并發訪問的一致性、有效性,是所有數據庫必須解決的一個問題,MySQL由于自身架構的特點,在不同的存儲引擎中,都設計了面對特定場景的鎖定機制,所以引擎的差別,導致鎖機制也是有很大差別的。
 
  鎖機制 :
 
  數據庫為了保證數據的一致性,而使用各種共享的資源在被并發訪問時變得有序所設計的一種規則。
 
  舉例:在電商網站購買商品時,商品表中只存有1個商品,而此時又有兩個人同時購買,那么誰能買到就是一個關鍵的問題。
 
  這里會用到事務進行一系列的操作:
 
  先從商品表中取出物品的數據
 
  然后插入訂單
 
  付款后,再插入付款表信息
 
  更新商品表中商品的數量
 
  以上過程中,使用鎖可以對商品數量數據信息進行保護,實現隔離,即只允許第一位用戶完成整套購買流程,而其他用戶只能等待,這樣就解決了并發中的矛盾問題。
 
  鎖的分類:
 
  按操作分類:
 
  共享鎖:也叫讀鎖。針對同一份數據,多個事務讀取操作可以同時加鎖而不互相影響 ,但是不能修改數據記錄。
 
  排他鎖:也叫寫鎖。當前的操作沒有完成前,會阻斷其他操作的讀取和寫入
 
  按粒度分類:
 
  表級鎖:操作時,會鎖定整個表。開銷小,加鎖快;不會出現死鎖;鎖定力度大,發生鎖沖突概率高,并發度最低。偏向于MyISAM存儲引擎!
 
  行級鎖:操作時,會鎖定當前操作行。開銷大,加鎖慢;會出現死鎖;鎖定粒度小,發生鎖沖突的概率低,并發度高。偏向于InnoDB存儲引擎!
 
  頁級鎖:鎖的粒度、發生沖突的概率和加鎖的開銷介于表鎖和行鎖之間,會出現死鎖,并發性能一般。
 
  按使用方式分類:
 
  悲觀鎖:每次查詢數據時都認為別人會修改,很悲觀,所以查詢時加鎖。
 
  樂觀鎖:每次查詢數據時都認為別人不會修改,很樂觀,但是更新時會判斷一下在此期間別人有沒有去更新這個數據
 
  不同存儲引擎支持的鎖
 
  mysql鎖機制的概念是什么
 
  共享鎖:
 
  多個共享鎖之間可以共享,如果是有鍵的話InnoDB默認是行鎖,沒有的話就會提升到表鎖,是行鎖時多個窗口可以修改不同行的數據,同行的話需要等先加鎖的提交,不同行可以直接修改,但是另外一個要查詢也要等后面修改的提交。提交完鎖就消失了
 
  共享鎖:
 
  SELECT語句 LOCK IN SHARE MODE;
 
  窗口1:
 
  - 窗口1
 
  /*
 
      共享鎖:數據可以被多個事務查詢,但是不能修改
 
  */
 
  -- 開啟事務
 
  START TRANSACTION;
 
  -- 查詢id為1的數據記錄。加入共享鎖
 
  SELECT * FROM student WHERE id=1 LOCK IN SHARE MODE;
 
  -- 查詢分數為99分的數據記錄。加入共享鎖
 
  SELECT * FROM student WHERE score=99 LOCK IN SHARE MODE;
 
  -- 提交事務
 
  COMMIT;
 
  窗口2:
 
  -- 窗口2
 
  -- 開啟事務
 
  START TRANSACTION;
 
  -- 查詢id為1的數據記錄(普通查詢,可以查詢)
 
  SELECT * FROM student WHERE id=1;
 
  -- 查詢id為1的數據記錄,并加入共享鎖(可以查詢。共享鎖和共享鎖兼容)
 
  SELECT * FROM student WHERE id=1 LOCK IN SHARE MODE;
 
  -- 修改id為1的姓名為張三三(不能修改,會出現鎖的情況。只有窗口1提交事務后,才能修改成功)
 
  UPDATE student SET NAME='張三三' WHERE id = 1;
 
  -- 修改id為2的姓名為李四四(修改成功,InnoDB引擎默認是行鎖)
 
  UPDATE student SET NAME='李四四' WHERE id = 2;
 
  -- 修改id為3的姓名為王五五(修改失敗,InnoDB引擎如果不采用帶索引的列加鎖。則會提升為表鎖)
 
  UPDATE student SET NAME='王五五' WHERE id = 3;
 
  -- 提交事務
 
  COMMIT;
 
  排他鎖:
 
  在排他鎖執行的時候,其他事務普通查詢可以,不可以加鎖任何操作
 
  -- 標準語法
 
  SELECT語句 FOR UPDATE;
 
  窗口1:
 
  -- 窗口1
 
  /*
 
      排他鎖:加鎖的數據,不能被其他事務加鎖查詢或修改
 
  */
 
  -- 開啟事務
 
  START TRANSACTION;
 
  -- 查詢id為1的數據記錄,并加入排他鎖
 
  SELECT * FROM student WHERE id=1 FOR UPDATE;
 
  -- 提交事務
 
  COMMIT;
 
  窗口2:
 
  -- 窗口2
 
  -- 開啟事務
 
  START TRANSACTION;
 
  -- 查詢id為1的數據記錄(普通查詢沒問題)
 
  SELECT * FROM student WHERE id=1;
 
  -- 查詢id為1的數據記錄,并加入共享鎖(不能查詢。因為排他鎖不能和其他鎖共存)
 
  SELECT * FROM student WHERE id=1 LOCK IN SHARE MODE;
 
  -- 查詢id為1的數據記錄,并加入排他鎖(不能查詢。因為排他鎖不能和其他鎖共存)
 
  SELECT * FROM student WHERE id=1 FOR UPDATE;
 
  -- 修改id為1的姓名為張三(不能修改,會出現鎖的情況。只有窗口1提交事務后,才能修改成功)
 
  UPDATE student SET NAME='張三' WHERE id=1;
 
  -- 提交事務
 
  COMMIT;
 
  MyISAM鎖:
 
  MyISAM讀鎖:
 
  myisam是加整個表的鎖,讀鎖的時候,不解鎖的話所有的事務可以查,不可以有其他任何操作包括本身事務也不可以操作
 
  -- 加鎖
 
  LOCK TABLE 表名 READ;
 
  -- 解鎖(將當前會話所有的表進行解鎖)
 
  UNLOCK TABLES;
 
  MyISAM寫鎖:
 
  寫鎖的時候,只要不解鎖其他事務不可以執行任何操作,本身事務可以操作
 
  -- 標準語法
 
  -- 加鎖
 
  LOCK TABLE 表名 WRITE;
 
  -- 解鎖(將當前會話所有的表進行解鎖)
 
  UNLOCK TABLES;
 
  悲觀鎖:
 
  就是很悲觀,它對于數據被外界修改的操作持保守態度,認為數據隨時會修改。
 
  整個數據處理中需要將數據加鎖。悲觀鎖一般都是依靠關系型數據庫提供的鎖機制。
 
  行鎖,表鎖不論是讀寫鎖都是悲觀鎖。
 
  樂觀鎖:
 
  就是很樂觀,每次自己操作數據的時候認為沒有人會來修改它,所以不去加鎖。
 
  但是在更新的時候會去判斷在此期間數據有沒有被修改。
 
  需要用戶自己去實現,不會發生并發搶占資源,只有在提交操作的時候檢查是否違反數據完整性。
 
  樂觀鎖的簡單實現方式:
 
  實現思想:加標記去比較,一樣則執行,不同則不執行
 
  方式一:版本號
 
  給數據表中添加一個version列,每次更新后都將這個列的值加1。
 
  讀取數據時,將版本號讀取出來,在執行更新的時候,比較版本號。
 
  如果相同則執行更新,如果不相同,說明此條數據已經發生了變化。
 
  用戶自行根據這個通知來決定怎么處理,比如重新開始一遍,或者放棄本次更新。
 
  -- 創建city表
 
  CREATE TABLE city(
 
      id INT PRIMARY KEY AUTO_INCREMENT,  -- 城市id
 
      NAME VARCHAR(20),                   -- 城市名稱
 
      VERSION INT                         -- 版本號
 
  );
 
  -- 添加數據
 
  INSERT INTO city VALUES (NULL,'北京',1),(NULL,'上海',1),(NULL,'廣州',1),(NULL,'深圳',1);
 
  -- 修改北京為北京市
 
  -- 1.查詢北京的version
 
  SELECT VERSION FROM city WHERE NAME='北京';
 
  -- 2.修改北京為北京市,版本號+1。并對比版本號
 
  UPDATE city SET NAME='北京市',VERSION=VERSION+1 WHERE NAME='北京' AND VERSION=1;
 
  方式二:時間戳
 
  和版本號方式基本一樣,給數據表中添加一個列,名稱無所謂,數據類型需要是timestamp
 
  每次更新后都將最新時間插入到此列。
 
  讀取數據時,將時間讀取出來,在執行更新的時候,比較時間。
 
  如果相同則執行更新,如果不相同,說明此條數據已經發生了變化。
 
  悲觀鎖和樂觀鎖使用前提:
 
  對于讀的操作遠多于寫的操作的時候,這時候一個更新操作加鎖會阻塞所有的讀取操作,降低了吞吐量。最后還要釋放鎖,鎖是需要一些開銷的,這時候可以選擇樂觀鎖。
 
  如果是讀寫比例差距不是非常大或者系統沒有響應不及時,吞吐量瓶頸的問題,那就不要去使用樂觀鎖,它增加了復雜度,也帶來了業務額外的風險。這時候可以選擇悲觀鎖。
 

(編輯:武林網)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 巫溪县| 孙吴县| 西乌珠穆沁旗| 武功县| 新晃| 怀来县| 南昌县| 宁国市| 陵水| 昂仁县| 三门峡市| 江永县| 三江| 余姚市| 竹溪县| 门头沟区| 巢湖市| 福安市| 荆州市| 漳浦县| 淄博市| 南皮县| 鄂托克前旗| 乳山市| 宁乡县| 曲麻莱县| 长白| 平凉市| 大关县| 黔西| 汉源县| 东台市| 元朗区| 香格里拉县| 西丰县| 湖南省| 土默特右旗| 嘉禾县| 荣成市| 大厂| 瓮安县|