1. 程式人生 > >數據庫 之 鎖的概念和顯示鎖的使用

數據庫 之 鎖的概念和顯示鎖的使用

進行 機制 可重復 插入數據 執行sql 就會 sdn 不一致 任務

1 概述

【為什麽要鎖】

當並發事務同時訪問一個資源時,有可能導致數據不一致,因此需要一種機制來將數據訪問順序化,以保證數據庫數據的一致性。鎖就是其中的一種機制。

數據庫是一個多用戶使用的共享資源,比如一個用戶表t_user,兩個瀏覽器前面的人登錄了同個一個賬號,把電話號碼改了。當多個用戶並發地存取數據時,在數據庫中就會產生多個事務同時存取同一數據的情況。若對並發操作不加控制就可能會讀取和存儲不正確的數據,破壞數據庫的一致性(臟讀,不可重復讀,幻讀等),可能產生死鎖。為了解決這個問題,加鎖是一個非常重要的技術,對實現數據庫並發控制是一個好的方案。簡單說,當一個執行sql語句的事務想要操作表記錄之前,先向數據庫發出請求,對你訪問的記錄集加鎖,在這個事務釋放這個鎖之前,其他事務不能對這些數據進行更新操作。

數據庫管理系統(DBMS)中的並發控制的任務是確保在多個事務同時存取數據庫中同一數據時不破壞事務的隔離性和統一性以及數據庫的統一性。下面舉例說明並發操作帶來的數據不一致性問題:

現有兩處火車票售票點,同時讀取某一趟列車車票數據庫中車票余額為 X。兩處售票點同時賣出一張車票,同時修改余額為 X -1寫回數據庫,這樣就造成了實際賣出兩張火車票而數據庫中的記錄卻只少了一張。 產生這種情況的原因是因為兩個事務讀入同一數據並同時修改,其中一個事務提交的結果破壞了另一個事務提交的結果,導致其數據的修改被丟失,破壞了事務的隔離性。並發控制要解決的就是這類問題。

封鎖、時間戳、樂觀並發控制(樂觀鎖)和悲觀並發控制(悲觀鎖)是並發控制主要采用的技術手段。

2 概念介紹

鎖類型 :

讀鎖:共享鎖,可被多個讀操作共享;只能共享給讀。

寫鎖:排它鎖,獨占鎖;

鎖粒度:

表鎖:在表級別施加鎖,並發性較低;表級鎖的粒度大於行級鎖

行鎖:在行級別施加鎖,並發性較高;維持鎖狀態的成本較大;

鎖的粒度越小,可能會造成死鎖的狀態。如兩行需要同時編輯的時候,互相需要等待另一行解鎖,造成了死鎖的情況。

鎖策略:在鎖粒度及數據安全性之間尋求一種平衡機制;使得並發機制正常,同時又能維持正常的鎖狀態。

存儲引擎級別的鎖:級別以及何時施加或釋放鎖由存儲引擎自行決定;由引擎決定

MySQL Server:表級別,可自行決定,也允許顯式請求;允許用戶手動請求和施加鎖,是表級別的。

鎖類別:

顯式鎖:用戶手動請求的鎖;

隱式鎖:存儲引擎自行根據需要施加的鎖;

3 顯式鎖的使用

(1) LOCK TABLES

LOCK TABLES tbl_name read|write, tbl_name read|write, ...

UNLOCK TABLES #解開全部的鎖,後面不跟表名

施加寫鎖,寫鎖是排他的,不允許別的線程讀和寫,自己施加鎖是不受影響

lock tables classlist write;

MariaDB [sunny]> lock tables classlist write;

Query OK, 0 rows affected (0.00 sec)

MariaDB [sunny]> select * from classlist; #此時是可以正常讀寫

Empty set (0.00 sec)

註意,此時當另一用戶連接的時候(從另一終端登錄該數據庫),查看的時候,結果就出不來,處於鎖住的狀態。

MariaDB [sunny]> select * from classlist;

施加讀鎖後,別的進程可以看,但是不能插入數據,讀鎖對寫鎖排斥,解鎖後才能正常

MariaDB [sunny]> lock tables classlist read;

Query OK, 0 rows affected (0.00 sec)

此時從另一終端登錄插入數據時是處於鎖住狀態

MariaDB [sunny]> insert into classlist values ("sunny",1,"100");

(2) FLUSH TABLES:將內存中的數據同步到磁盤上,即刷寫操作,但是這個同步過程可以施加鎖,一旦施加鎖的時候,即執行將對應的表同步,關閉,打開,並施加鎖。一旦施加了鎖,此時別的線程讀操作不受影響,但是寫操作將不能被執行,需要解鎖後才能生效

FLUSH TABLES tbl_name,... [WITH READ LOCK];

UNLOCK TABLES;

鎖住所有的表,註意,可以針對某張表進行上鎖

MariaDB [sunny]> flush tables with read lock;

Query OK, 0 rows affected (0.00 sec)

其他線程,解鎖後才能夠插入數據

MariaDB [sunny]> insert into classlist values ("tracy",2,"99");

Query OK, 1 row affected (1 min 5.58 sec)

(3) SELECT cluase #FOR UPDATE請求施加寫鎖,LOCK IN SHARE MODE施加讀鎖,一般不操作

[FOR UPDATE | LOCK IN SHARE MODE]

一般要操作的是手動解鎖。但是可能會對已經在軟件層的操作造成影響。

更多介紹建議參考鏈接:

數據庫的鎖機制:http://blog.csdn.net/lexang1/article/details/52248686

數據庫為什麽需要鎖機制?有哪些鎖機制?:https://www.cnblogs.com/fanp/p/4633453.html

數據庫 之 鎖的概念和顯示鎖的使用