回覆列表
  • 1 # 程式汪汪

    唯一約束

    資料庫裡有一個技術叫唯一約束

    事務控制

    程式碼裡有個技術叫事務控制

    分資料庫的鎖和程式碼裡的鎖

  • 2 # SunnyZhang的IT世界

    所謂併發,從概念可以看出其並不是並行,在使用者的角度來看有一種同時執行的錯覺,但在資料庫內部確實序列的,或者說在某種粒度是序列的。

    以更新表中某一行資料為例,在更新時會對改行資料加鎖,避免其它程序對該行的訪問,從而避免資料衝突。

    除此以外,還有其它各種鎖來適應不同的場景。所以,我們所謂的併發場景下,並不會出現數據問題。

  • 3 # 列克美食

    儲存引擎檢視

    MySQL給開發者提供了查詢儲存引擎的功能,我這裡使用的是MySQL5.6.4,可以使用:

    SHOW ENGINES

    begin!

    樂觀鎖

    用資料版本(Version)記錄機制實現,這是樂觀鎖最常用的一種實現方式。何謂資料版本?即為資料增加一個版本標識,一般是透過為資料庫表增加一個數字型別的 “version” 欄位來實現。當讀取資料時,將version欄位的值一同讀出,資料每更新一次,對此version值加1。當我們提交更新的時候,判斷資料庫表對應記錄的當前版本資訊與第一次取出來的version值進行比對,如果資料庫表當前版本號與第一次取出來的version值相等,則予以更新,否則認為是過期資料。

    舉例

    1、資料庫表設計

    三個欄位,分別是id,value、version

    select id,value,version from TABLE where id=#{id}

    2、每次更新表中的value欄位時,為了防止發生衝突,需要這樣操作

    update TABLE set value=2,version=version+1 where id=#{id} and version=#{version}; 悲觀鎖

    與樂觀鎖相對應的就是悲觀鎖了。悲觀鎖就是在操作資料時,認為此操作會出現資料衝突,所以在進行每次操作時都要透過獲取鎖才能進行對相同資料的操作,這點跟java中的synchronized很相似,所以悲觀鎖需要耗費較多的時間。另外與樂觀鎖相對應的,悲觀鎖是由資料庫自己實現了的,要用的時候,我們直接呼叫資料庫的相關語句就可以了。

    說到這裡,由悲觀鎖涉及到的另外兩個鎖概念就出來了,它們就是共享鎖與排它鎖。共享鎖和排它鎖是悲觀鎖的不同的實現,它倆都屬於悲觀鎖的範疇。

    使用,排它鎖 舉例

    要使用悲觀鎖,我們必須關閉mysql資料庫的自動提交屬性,因為MySQL預設使用autocommit模式,也就是說,當你執行一個更新操作後,MySQL會立刻將結果進行提交。

    我們可以使用命令設定MySQL為非autocommit模式:

    set autocommit=0; # 設定完autocommit後,我們就可以執行我們的正常業務了。具體如下: # 1. 開始事務 begin;/begin work;/start transaction; (三者選一就可以) # 2. 查詢表資訊 select status from TABLE where id=1 for update; # 3. 插入一條資料 insert into TABLE (id,value) values (2,2); # 4. 修改資料為 update TABLE set value=2 where id=1; # 5. 提交事務 commit;/commit work; 共享鎖

    共享鎖又稱讀鎖 read lock,是讀取操作建立的鎖。其他使用者可以併發讀取資料,但任何事務都不能對資料進行修改(獲取資料上的排他鎖),直到已釋放所有共享鎖。

    如果事務T對資料A加上共享鎖後,則其他事務只能對A再加共享鎖,不能加排他鎖。獲得共享鎖的事務只能讀資料,不能修改資料

    開啟第一個查詢視窗

    begin;/begin work;/start transaction; (三者選一就可以) SELECT * from TABLE where id = 1 lock in share mode;

    然後在另一個查詢視窗中,對id為1的資料進行更新

    update TABLE set name="www.souyunku.com" where id =1;

    此時,操作介面進入了卡頓狀態,過了超時間,提示錯誤資訊

    如果在超時前,執行 commit,此更新語句就會成功。

    [SQL]update test_one set name="www.souyunku.com" where id =1; [Err] 1205 - Lock wait timeout exceeded; try restarting transaction

    加上共享鎖後,也提示錯誤資訊

    update test_one set name="www.souyunku.com" where id =1 lock in share mode; [SQL]update test_one set name="www.souyunku.com" where id =1 lock in share mode; [Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near "lock in share mode" at line 1

    在查詢語句後面增加LOCK IN SHARE MODE,Mysql會對查詢結果中的每行都加共享鎖,當沒有其他執行緒對查詢結果集中的任何一行使用排他鎖時,可以成功申請共享鎖,否則會被阻塞。其他執行緒也可以讀取使用了共享鎖的表,而且這些執行緒讀取的是同一個版本的資料。

    加上共享鎖後,對於update,insert,delete語句會自動加排它鎖。

    排它鎖

    排他鎖 exclusive lock(也叫writer lock)又稱寫鎖。

    排它鎖是悲觀鎖的一種實現,在上面悲觀鎖也介紹過。

    若事務 1 對資料物件A加上X鎖,事務 1 可以讀A也可以修改A,其他事務不能再對A加任何鎖,直到事物 1 釋放A上的鎖。這保證了其他事務在事物 1 釋放A上的鎖之前不能再讀取和修改A。排它鎖會阻塞所有的排它鎖和共享鎖

    讀取為什麼要加讀鎖呢:防止資料在被讀取的時候被別的執行緒加上寫鎖,

    使用方式:在需要執行的語句後面加上for update就可以了

    行鎖

    行鎖又分共享鎖和排他鎖,由字面意思理解,就是給某一行加上鎖,也就是一條記錄加上鎖。

    注意:行級鎖都是基於索引的,如果一條SQL語句用不到索引是不會使用行級鎖的,會使用表級鎖。

    共享鎖:

    名詞解釋:共享鎖又叫做讀鎖,所有的事務只能對其進行讀操作不能寫操作,加上共享鎖後在事務結束之前其他事務只能再加共享鎖,除此之外其他任何型別的鎖都不能再加了。

    SELECT * from TABLE where id = "1" lock in share mode; 結果集的資料都會加共享鎖

    排他鎖:

    名詞解釋:若某個事物對某一行加上了排他鎖,只能這個事務對其進行讀寫,在此事務結束之前,其他事務不能對其進行加任何鎖,其他程序可以讀取,不能進行寫操作,需等待其釋放。

    select status from TABLE where id=1 for update;

    可以參考之前演示的共享鎖,排它鎖語句

    由於對於表中,id欄位為主鍵,就也相當於索引。執行加鎖時,會將id這個索引為1的記錄加上鎖,那麼這個鎖就是行鎖。

    表鎖

    如何加表鎖

    innodb 的行鎖是在有索引的情況下,沒有索引的表是鎖定全表的.

    Innodb中的行鎖與表鎖

    前面提到過,在Innodb引擎中既支援行鎖也支援表鎖,那麼什麼時候會鎖住整張表,什麼時候或只鎖住一行呢?

    只有透過索引條件檢索資料,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖!

    在實際應用中,要特別注意InnoDB行鎖的這一特性,不然的話,可能導致大量的鎖衝突,從而影響併發效能。

    行級鎖都是基於索引的,如果一條SQL語句用不到索引是不會使用行級鎖的,會使用表級鎖。行級鎖的缺點是:由於需要請求大量的鎖資源,所以速度慢,記憶體消耗大。

    死鎖

    死鎖(Deadlock)

    所謂死鎖:是指兩個或兩個以上的程序在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的程序稱為死鎖程序。由於資源佔用是互斥的,當某個程序提出申請資源後,使得有關程序在無外力協助下,永遠分配不到必需的資源而無法繼續執行,這就產生了一種特殊現象死鎖。

    解除正在死鎖的狀態有兩種方法:

    第一種:

    1.查詢是否鎖表

    show OPEN TABLES where In_use > 0;

    2.查詢程序(如果您有SUPER許可權,您可以看到所有執行緒。否則,您只能看到您自己的執行緒)

    show processlist

    3.殺死程序id(就是上面命令的id列)

    kill id

    第二種:

    1:檢視當前的事務

    SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

    2:檢視當前鎖定的事務

    SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

    3:檢視當前等鎖的事務

    SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

    殺死程序

    kill 執行緒ID

    如果系統資源充足,程序的資源請求都能夠得到滿足,死鎖出現的可能性就很低,否則就會因爭奪有限的資源而陷入死鎖。其次,程序執行推進順序與速度不同,也可能產生死鎖。

    產生死鎖的四個必要條件:

    (1) 互斥條件:一個資源每次只能被一個程序使用。

    (2) 請求與保持條件:一個程序因請求資源而阻塞時,對已獲得的資源保持不放。

    (3) 不剝奪條件:程序已獲得的資源,在末使用完之前,不能強行剝奪。

    (4) 迴圈等待條件:若干程序之間形成一種頭尾相接的迴圈等待資源關係。

    雖然不能完全避免死鎖,但可以使死鎖的數量減至最少。將死鎖減至最少可以增加事務的吞吐量並減少系統開銷,因為只有很少的事務回滾,而回滾會取消事務執行的所有工作。由於死鎖時回滾而由應用程式重新提交。

    下列方法有助於最大限度地降低死鎖:

    (1)按同一順序訪問物件。

    (2)避免事務中的使用者互動。

    (3)保持事務簡短並在一個批處理中。

    (4)使用低隔離級別。

    (5)使用繫結連線。

  • 中秋節和大豐收的關聯?
  • 跌入谷底,又重回巔峰的胡歌,靠的是運氣嗎?