首頁  >  文章  >  資料庫  >  mysql鎖機制的概念是什麼

mysql鎖機制的概念是什麼

王林
王林轉載
2023-06-03 18:01:301145瀏覽

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

每次更新后都将最新时间插入到此列。

读取数据时,将时间读取出来,在执行更新的时候,比较时间。

如果相同则执行更新,如果不相同,说明此条数据已经发生了变化。

悲观锁和乐观锁使用前提:

当读取操作远多于写操作时,更新操作被加锁会阻塞所有读取操作,降低了系统的吞吐量。最后还要释放锁,锁是需要一些开销的,这时候可以选择乐观锁。

如果是读写比例差距不是非常大或者系统没有响应不及时,吞吐量瓶颈的问题,那就不要去使用乐观锁,它增加了复杂度,也带来了业务额外的风险。这时候可以选择悲观锁。

以上是mysql鎖機制的概念是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除