深入淺出Mysql—鎖霎终、事務(wù)與并發(fā)控制看這篇就夠了

mysql服務(wù)器邏輯架構(gòu)

每個(gè)連接都會(huì)在mysql服務(wù)端產(chǎn)生一個(gè)線程(內(nèi)部通過(guò)線程池管理線程)喝滞,比如一個(gè)select語(yǔ)句進(jìn)入红竭,mysql首先會(huì)在查詢緩存中查找是否緩存了這個(gè)select的結(jié)果集影涉,如果沒有則繼續(xù)執(zhí)行 解析变隔、優(yōu)化、執(zhí)行的過(guò)程蟹倾;否則會(huì)之間從緩存中獲取結(jié)果集匣缘。


mysql并發(fā)控制——共享鎖、排他鎖

共享鎖

共享鎖也稱讀鎖鲜棠,讀鎖允許多個(gè)連接可以同一時(shí)刻并發(fā)的讀取同一資源,互不干擾肌厨;

排他鎖

排他鎖也稱寫鎖,一個(gè)寫鎖會(huì)阻塞其他的寫鎖或讀鎖豁陆,保證同一時(shí)刻只有一個(gè)連接可以寫入數(shù)據(jù)柑爸,同時(shí)防止其他用戶對(duì)這個(gè)數(shù)據(jù)的讀寫。

鎖策略

鎖的開銷是較為昂貴的盒音,鎖策略其實(shí)就是保證了線程安全的同時(shí)獲取最大的性能之間的平衡策略表鳍。


mysql鎖策略:talbe lock(表鎖)

表鎖是mysql最基本的鎖策略馅而,也是開銷最小的鎖,它會(huì)鎖定整個(gè)表进胯。

具體情況是:若一個(gè)用戶正在執(zhí)行寫操作用爪,會(huì)獲取排他的“寫鎖”,這可能會(huì)鎖定整個(gè)表胁镐,阻塞其他用戶的讀偎血、寫操作;若一個(gè)用戶正在執(zhí)行讀操作盯漂,會(huì)先獲取共享鎖“讀鎖”颇玷,這個(gè)鎖運(yùn)行其他讀鎖并發(fā)的對(duì)這個(gè)表進(jìn)行讀取,互不干擾就缆。只要沒有寫鎖的進(jìn)入帖渠,讀鎖可以是并發(fā)讀取統(tǒng)一資源的。

通常發(fā)生在DDL語(yǔ)句DML不走索引的語(yǔ)句中竭宰,比如這個(gè)DML update table set columnA=”A” where columnB=“B”.

如果columnB字段不存在索引(或者不是組合索引前綴)空郊,會(huì)鎖住所有記錄也就是鎖表;如果語(yǔ)句的執(zhí)行能夠執(zhí)行一個(gè)columnB字段的索引切揭,那么會(huì)鎖住滿足where的行(行鎖)狞甚。

mysql鎖策略:row lock(行鎖)

行鎖可以最大限度的支持并發(fā)處理,當(dāng)然也帶來(lái)了最大開銷廓旬,顧名思義哼审,行鎖的粒度實(shí)在每一條行數(shù)據(jù)。


事務(wù)


事務(wù)就是一組原子性的sql孕豹,或者說(shuō)一個(gè)獨(dú)立的工作單元涩盾。事務(wù)就是說(shuō),要么mysql引擎會(huì)全部執(zhí)行這一組sql語(yǔ)句励背,要么全部都不執(zhí)行(比如其中一條語(yǔ)句失敗的話)春霍。

比如,tim要給bill轉(zhuǎn)賬100塊錢:

1.檢查tim的賬戶余額是否大于100塊叶眉;

2.tim的賬戶減少100塊终畅;

3.bill的賬戶增加100塊;

這三個(gè)操作就是一個(gè)事務(wù)竟闪,必須打包執(zhí)行离福,要么全部成功,要么全部不執(zhí)行炼蛤,其中任何一個(gè)操作的失敗都會(huì)導(dǎo)致所有三個(gè)操作“不執(zhí)行”——回滾妖爷。

CREATE DATABASE IF NOT EXISTS employees;

USE employees;

CREATE TABLE `employees`.`account` (

`id` BIGINT (11) NOT NULL AUTO_INCREMENT,

`p_name` VARCHAR (4),

`p_money` DECIMAL (10, 2) NOT NULL DEFAULT 0,

PRIMARY KEY (`id`)

) ;

INSERT INTO `employees`.`account` (`id`, `p_name`, `p_money`) VALUES ('1', 'tim', '200');

INSERT INTO `employees`.`account` (`id`, `p_name`, `p_money`) VALUES ('2', 'bill', '200');

START TRANSACTION;

SELECT p_money FROM account WHERE p_name="tim";-- step1

UPDATE account SET p_money=p_money-100 WHERE p_name="tim";-- step2

UPDATE account SET p_money=p_money+100 WHERE p_name="bill";-- step3

COMMIT;


一個(gè)良好的事務(wù)系統(tǒng),必須滿足ACID特點(diǎn)


A:atomiciy原子性

一個(gè)事務(wù)必須保證其中的操作要么全部執(zhí)行,要么全部回滾絮识,不可能存在只執(zhí)行了一部分這種情況出現(xiàn)绿聘。

C:consistency一致性

數(shù)據(jù)必須保證從一種一致性的狀態(tài)轉(zhuǎn)換為另一種一致性狀態(tài)。比如上一個(gè)事務(wù)中執(zhí)行了第二步時(shí)系統(tǒng)崩潰了次舌,數(shù)據(jù)也不會(huì)出現(xiàn)bill的賬戶少了100塊熄攘,但是tim的賬戶沒變的情況;要么維持原裝(全部回滾)彼念,要么bill少了100塊同時(shí)tim多了100塊挪圾,只有這兩種一致性狀態(tài)的。

I:isolation隔離性

在一個(gè)事務(wù)未執(zhí)行完畢時(shí)逐沙,通常會(huì)保證其他Session 無(wú)法看到這個(gè)事務(wù)的執(zhí)行結(jié)果

D:durability持久性

事務(wù)一旦commit哲思,則數(shù)據(jù)就會(huì)保存下來(lái),即使提交完之后系統(tǒng)崩潰吩案,數(shù)據(jù)也不會(huì)丟失棚赔。


隔離級(jí)別


查看系統(tǒng)隔離級(jí)別:

select @@global.tx_isolation;

查看當(dāng)前會(huì)話隔離級(jí)別

select @@tx_isolation;

設(shè)置當(dāng)前會(huì)話隔離級(jí)別

SET session TRANSACTION ISOLATION LEVEL serializable;

設(shè)置全局系統(tǒng)隔離級(jí)別

SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;


READ UNCOMMITTED(未提交讀,可臟讀)


事務(wù)中的修改,即使沒有提交徘郭,對(duì)其他會(huì)話也是可見的靠益。

可以讀取未提交的數(shù)據(jù)——臟讀,臟讀會(huì)導(dǎo)致很多問(wèn)題残揉,一般不適用這個(gè)隔離級(jí)別捆毫。

實(shí)例:

-- ------------------------- read-uncommitted實(shí)例 ------------------------------

-- 設(shè)置全局系統(tǒng)隔離級(jí)別

SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

-- Session A

START TRANSACTION;

SELECT * FROM USER;

UPDATE USER SET NAME="READ UNCOMMITTED";

-- commit;

-- Session B

SELECT * FROM USER;

//SessionB Console 可以看到Session A未提交的事物處理,在另一個(gè)Session 中也看到了冲甘,這就是所謂的臟讀

id name

2 READ UNCOMMITTED

34 READ UNCOMMITTED


READ COMMITTED(提交讀或不可重復(fù)讀,幻讀)


一般數(shù)據(jù)庫(kù)都默認(rèn)使用這個(gè)隔離級(jí)別(mysql不是)途样,這個(gè)隔離級(jí)別保證了一個(gè)事務(wù)如果沒有完全成功(commit執(zhí)行完)江醇,事務(wù)中的操作對(duì)其他會(huì)話是不可見的

-- ------------------------- read-cmmitted實(shí)例 ------------------------------

-- 設(shè)置全局系統(tǒng)隔離級(jí)別

SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- Session A

START TRANSACTION;

SELECT * FROM USER;

UPDATE USER SET NAME="READ COMMITTED";

-- COMMIT;

-- Session B

SELECT * FROM USER;

//Console OUTPUT:

id name

2 READ UNCOMMITTED

34 READ UNCOMMITTED

---------------------------------------------------

-- 當(dāng) Session A執(zhí)行了commit何暇,Session B得到如下結(jié)果:

id name

2 READ COMMITTED

34 READ COMMITTED

也驗(yàn)證了read committed級(jí)別在事物未完成commit操作之前修改的數(shù)據(jù)對(duì)其他Session 不可見陶夜,執(zhí)行了commit之后才會(huì)對(duì)其他Session可見。

我們可以看到Session B兩次查詢得到了不同的數(shù)據(jù)裆站。

read committed隔離級(jí)別解決了臟讀的問(wèn)題条辟,但是會(huì)對(duì)其他Session 產(chǎn)生兩次不一致的讀取結(jié)果(因?yàn)榱硪粋€(gè)Session 執(zhí)行了事務(wù),一致性變化)宏胯。


REPEATABLE READ(可重復(fù)讀)


一個(gè)事務(wù)中多次執(zhí)行統(tǒng)一讀SQL羽嫡,返回結(jié)果一樣。這個(gè)隔離級(jí)別解決了臟讀的問(wèn)題肩袍,幻讀問(wèn)題杭棵。這里指的是innodb的rr級(jí)別,innodb中使用next-key鎖對(duì)”當(dāng)前讀”進(jìn)行加鎖氛赐,鎖住行以及可能產(chǎn)生幻讀的插入位置魂爪,阻止新的數(shù)據(jù)插入產(chǎn)生幻行先舷。

SERIALIZABLE(可串行化)

最強(qiáng)的隔離級(jí)別,通過(guò)給事務(wù)中每次讀取的行加鎖滓侍,寫加寫鎖蒋川,保證不產(chǎn)生幻讀問(wèn)題,但是會(huì)導(dǎo)致大量超時(shí)以及鎖爭(zhēng)用問(wèn)題撩笆。

多版本并發(fā)控制-MVCC

MVCC(multiple-version-concurrency-control)是個(gè)行級(jí)鎖的變種捺球,它在普通讀情況下避免了加鎖操作,因此開銷更低浇衬。雖然實(shí)現(xiàn)不同懒构,但通常都是實(shí)現(xiàn)非阻塞讀,對(duì)于寫操作只鎖定必要的行耘擂。

一致性讀 (就是讀取快照)

select * from table ….;

當(dāng)前讀(就是讀取實(shí)際的持久化的數(shù)據(jù))

特殊的讀操作胆剧,插入/更新/刪除操作,屬于當(dāng)前讀醉冤,處理的都是當(dāng)前的數(shù)據(jù)秩霍,需要加鎖。

select * from table where ? lock in share mode;

select * from table where ? for update;

insert;

update ;

delete;

注意:select …… from where…… (沒有額外加鎖后綴)使用MVCC蚁阳,保證了讀快照(mysql稱為consistent read)铃绒,所謂一致性讀或者讀快照就是讀取當(dāng)前事務(wù)開始之前的數(shù)據(jù)快照,在這個(gè)事務(wù)開始之后的更新不會(huì)被讀到螺捐。

對(duì)于加鎖讀SELECT with FOR UPDATE(排他鎖) or LOCK IN SHARE MODE(共享鎖)颠悬、update、delete語(yǔ)句定血,要考慮是否是唯一索引的等值查詢赔癌。

寫鎖-recordLock,gapLock,next key lock

對(duì)于使用到唯一索引 等值查詢:比如,where columnA=”…” 澜沟,如果columnA上的索引被使用到灾票,那么會(huì)在滿足where的記錄上加行鎖(for update是排他鎖,lock in shared 是共享鎖,其他寫操作加排他鎖)茫虽。這里是行級(jí)鎖刊苍,record lock。

對(duì)于范圍查詢(使用非唯一的索引):

比如(做范圍查詢):where columnA between 10 and 30 ,會(huì)導(dǎo)致其他會(huì)話中10以后的數(shù)據(jù)都無(wú)法插入(next key lock),從而解決了幻讀問(wèn)題濒析。這里是next key lock 會(huì)包括涉及到的所有行正什。next key lock=recordLock+gapLock,不僅鎖住相關(guān)數(shù)據(jù)号杏,而且鎖住邊界埠忘,從而徹底避免幻讀。

對(duì)于沒有索引

鎖表

通常發(fā)生在DDL語(yǔ)句DML不走索引的語(yǔ)句中,比如這個(gè)DML update table set columnA=”A” where columnB=“B”.如果columnB字段不存在索引(或者不是組合索引前綴)莹妒,會(huì)鎖住所有記錄也就是鎖表名船;如果語(yǔ)句的執(zhí)行能夠執(zhí)行一個(gè)columnB字段的索引,那么會(huì)鎖住滿足where的行(行鎖)旨怠。

INNODB的MVCC通常是通過(guò)在每行數(shù)據(jù)后邊保存兩個(gè)隱藏的列來(lái)實(shí)現(xiàn)(其實(shí)是三列渠驼,第三列是用于事務(wù)回滾,此處略去)鉴腻,一個(gè)保存了行的創(chuàng)建版本號(hào)迷扇,另一個(gè)保存了行的更新版本號(hào)(上一次被更新數(shù)據(jù)的版本號(hào)),這個(gè)版本號(hào)是每個(gè)事務(wù)的版本號(hào)爽哎,遞增的蜓席。這樣保證了innodb對(duì)讀操作不需要加鎖也能保證正確讀取數(shù)據(jù)。


MVCC select無(wú)鎖操作 與 維護(hù)版本號(hào)


下邊在mysql默認(rèn)的Repeatable Read隔離級(jí)別下,具體看看MVCC操作:

Select(快照讀,所謂讀快照就是讀取當(dāng)前事務(wù)之前的數(shù)據(jù)遣总。):

a.InnoDB只select查找版本號(hào)早于當(dāng)前版本號(hào)的數(shù)據(jù)行心墅,這樣保證了讀取的數(shù)據(jù)要么是在這個(gè)事務(wù)開始之前就已經(jīng)commit了的(早于當(dāng)前版本號(hào))猜敢,要么是在這個(gè)事務(wù)自身中執(zhí)行創(chuàng)建操作的數(shù)據(jù)(等于當(dāng)前版本號(hào))。

b.查找行的更新版本號(hào)要么未定義,要么大于當(dāng)前的版本號(hào)(為了保證事務(wù)可以讀到老數(shù)據(jù)),這樣保證了事務(wù)讀取到在當(dāng)前事務(wù)開始之后未被更新的數(shù)據(jù)瞭亮。

注意: 這里的select不能有for update、lock in share 語(yǔ)句固棚。

總之要只返回滿足以下條件的行數(shù)據(jù)统翩,達(dá)到了快照讀的效果:

(行創(chuàng)建版本號(hào)< =當(dāng)前版本號(hào) && (行更新版本號(hào)==null or 行更新版本號(hào)>當(dāng)前版本號(hào) ) )

Insert

InnoDB為這個(gè)事務(wù)中新插入的行,保存當(dāng)前事務(wù)版本號(hào)的行作為行的行創(chuàng)建版本號(hào)此洲。

Delete

InnoDB為每一個(gè)刪除的行保存當(dāng)前事務(wù)版本號(hào)厂汗,作為行的刪除標(biāo)記。

Update

將存在兩條數(shù)據(jù)黍翎,保持當(dāng)前版本號(hào)作為更新后的數(shù)據(jù)的新增版本號(hào),同時(shí)保存當(dāng)前版本號(hào)作為老數(shù)據(jù)行的更新版本號(hào)艳丛。

當(dāng)前版本號(hào)—寫—>新數(shù)據(jù)行創(chuàng)建版本號(hào) && 當(dāng)前版本號(hào)—寫—>老數(shù)據(jù)更新版本號(hào)();


臟讀 vs 幻讀 vs 不可重復(fù)讀


臟讀一事務(wù)未提交的中間狀態(tài)的更新數(shù)據(jù) 被其他會(huì)話讀取到匣掸。當(dāng)一個(gè)事務(wù)正在訪問(wèn)數(shù)據(jù),并且對(duì)數(shù)據(jù)進(jìn)行了修改氮双,而這種修改還沒有 提交到數(shù)據(jù)庫(kù)中(commit未執(zhí)行)碰酝,這時(shí),另外會(huì)話也訪問(wèn)這個(gè)數(shù)據(jù)戴差,因?yàn)檫@個(gè)數(shù)據(jù)是還沒有提交送爸, 那么另外一個(gè)會(huì)話讀到的這個(gè)數(shù)據(jù)是臟數(shù)據(jù),依據(jù)臟數(shù)據(jù)所做的操作也可能是不正確的。

不可重復(fù)讀簡(jiǎn)單來(lái)說(shuō)就是在一個(gè)事務(wù)中讀取的數(shù)據(jù)可能產(chǎn)生變化袭厂,ReadCommitted也稱不可重復(fù)讀墨吓。在同一事務(wù)中,多次讀取同一數(shù)據(jù)返回的結(jié)果有所不同纹磺,換句話說(shuō)帖烘,后續(xù)讀取可以讀到另一會(huì)話事務(wù)已提交的更新數(shù)據(jù)。 相反橄杨,“可重復(fù)讀”在同一事務(wù)中多次讀取數(shù)據(jù)時(shí)秘症,能夠保證所讀數(shù)據(jù)一樣,也就是式矫,后續(xù)讀取不能讀到另一會(huì)話事務(wù)已提交的更新數(shù)據(jù)乡摹。

幻讀:會(huì)話T1事務(wù)中執(zhí)行一次查詢,然后會(huì)話T2新插入一行記錄采转,這行記錄恰好可以滿足T1所使用的查詢的條件聪廉;然后T1又使用相同 的查詢?cè)俅螌?duì)表進(jìn)行檢索,但是此時(shí)卻看到了事務(wù)T2剛才插入的新行氏义。這個(gè)新行就稱為“幻像”锄列,因?yàn)閷?duì)T1來(lái)說(shuō)這一行就像突然 出現(xiàn)的一樣。

innoDB的RR級(jí)別無(wú)法做到完全避免幻讀惯悠,下文詳細(xì)分析邻邮。

----------------------------------前置準(zhǔn)備----------------------------------------

prerequisite:

-- 創(chuàng)建表

mysql>

CREATE TABLE `t_bitfly` (

`id` bigint(20) NOT NULL DEFAULT '0',

`value` varchar(32) DEFAULT NULL,

PRIMARY KEY (`id`)

)

-- 確保當(dāng)前隔離級(jí)別為默認(rèn)的RR級(jí)別

mysql> select @@global.tx_isolation, @@tx_isolation;

+-----------------------+-----------------+

| @@global.tx_isolation | @@tx_isolation |

+-----------------------+-----------------+

| REPEATABLE-READ | REPEATABLE-READ |

+-----------------------+-----------------+

1 row in set (0.00 sec)

---------------------------------------開始---------------------------------------------

session A | session B

|

|

mysql> START TRANSACTION; | mysql> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec) | Query OK, 0 rows affected (0.00 sec)

|

|

mysql> SELECT * FROM test.t_bitfly; | mysql> SELECT * FROM test.t_bitfly;

Empty set (0.00 sec) | Empty set (0.00 sec)

|

| mysql> INSERT INTO t_bitfly VALUES (1, 'test');

| Query OK, 1 row affected (0.00 sec)

|

|

mysql> SELECT * FROM test.t_bitfly; |

Empty set (0.00 sec) |

|

| mysql> commit;

| Query OK, 0 rows affected (0.01 sec)

mysql> SELECT * FROM test.t_bitfly; |

Empty set (0.00 sec) |

-- 可以看到雖然兩次執(zhí)行結(jié)果返回的數(shù)據(jù)一致, |

-- 但是不能說(shuō)明沒有幻讀克婶。接著看: |

|

mysql> INSERT INTO t_bitfly VALUES (1, 'test'); |

ERROR 1062 (23000): |

Duplicate entry '1' for key 'PRIMARY' |

|

-- 明明為空的表筒严,為什么說(shuō)主鍵重復(fù)?——幻讀出現(xiàn) G橛Q纪堋!?


如何保證rr級(jí)別絕對(duì)不產(chǎn)生幻讀筋岛?


在使用的select …where語(yǔ)句中加入 for update(排他鎖) 或者 lock in share mode(共享鎖)語(yǔ)句來(lái)實(shí)現(xiàn)娶视,其實(shí)就是鎖住了可能造成幻讀的數(shù)據(jù),阻止數(shù)據(jù)的寫入操作睁宰。

因?yàn)閿?shù)據(jù)的寫入操作(insert 肪获、update)需要先獲取寫鎖,由于可能產(chǎn)生幻讀的部分柒傻,已經(jīng)獲取到了某種鎖孝赫,所以要在另外一個(gè)會(huì)話中獲取寫鎖的前提是當(dāng)前會(huì)話中釋放所有因加鎖語(yǔ)句產(chǎn)生的鎖。

mysql死鎖問(wèn)題

死鎖红符,就是產(chǎn)生了循環(huán)等待鏈條青柄,我等待你的資源伐债,你卻等待我的資源,我們都相互等待致开,誰(shuí)也不釋放自己占有的資源峰锁,導(dǎo)致無(wú)線等待下去。

比如:

//Session A

START TRANSACTION;

UPDATE account SET p_money=p_money-100 WHERE p_name="tim";

UPDATE account SET p_money=p_money+100 WHERE p_name="bill";

COMMIT;

//Thread B

START TRANSACTION;

UPDATE account SET p_money=p_money+100 WHERE p_name="bill";

UPDATE account SET p_money=p_money-100 WHERE p_name="tim";

COMMIT;

當(dāng)線程A執(zhí)行到第一條語(yǔ)句UPDATE account SET p_money=p_money-100 WHERE p_name=”tim”;鎖定了p_name=”tim”的行數(shù)據(jù)喇喉;并且試圖獲取p_name=”bill”的數(shù)據(jù)祖今;此時(shí),恰好拣技,線程B也執(zhí)行到第一條語(yǔ)句:UPDATE account SET p_money=p_money+100 WHERE p_name=”bill”;

鎖定了 p_name=”bill”的數(shù)據(jù)千诬,同時(shí)試圖獲取p_name=”tim”的數(shù)據(jù);

此時(shí)膏斤,兩個(gè)線程就進(jìn)入了死鎖徐绑,誰(shuí)也無(wú)法獲取自己想要獲取的資源,進(jìn)入無(wú)線等待中莫辨,直到超時(shí)傲茄!


innodb_lock_wait_timeout 等待鎖超時(shí)回滾事務(wù):

直觀方法是在兩個(gè)事務(wù)相互等待時(shí),當(dāng)一個(gè)等待時(shí)間超過(guò)設(shè)置的某一閥值時(shí)沮榜,對(duì)其中一個(gè)事務(wù)進(jìn)行回滾盘榨,另一個(gè)事務(wù)就能繼續(xù)執(zhí)行。這種方法簡(jiǎn)單有效蟆融,在innodb中草巡,參數(shù)innodb_lock_wait_timeout用來(lái)設(shè)置超時(shí)時(shí)間。

wait-for graph算法來(lái)主動(dòng)進(jìn)行死鎖檢測(cè):

innodb還提供了wait-for graph算法來(lái)主動(dòng)進(jìn)行死鎖檢測(cè)型酥,每當(dāng)加鎖請(qǐng)求無(wú)法立即滿足需要并進(jìn)入等待時(shí)山憨,wait-for graph算法都會(huì)被觸發(fā)。


如何盡可能避免死鎖


1)以固定的順序訪問(wèn)表和行弥喉。比如兩個(gè)更新數(shù)據(jù)的事務(wù)郁竟,事務(wù)A 更新數(shù)據(jù)的順序 為1,2由境;事務(wù)B更新數(shù)據(jù)的順序?yàn)?棚亩,1。這樣更可能會(huì)造成死鎖虏杰。

2)大事務(wù)拆小讥蟆。大事務(wù)更傾向于死鎖,如果業(yè)務(wù)允許嘹屯,將大事務(wù)拆小攻询。

3)在同一個(gè)事務(wù)中从撼,盡可能做到一次鎖定所需要的所有資源州弟,減少死鎖概率钧栖。

4)降低隔離級(jí)別。如果業(yè)務(wù)允許婆翔,將隔離級(jí)別調(diào)低也是較好的選擇拯杠,比如將隔離級(jí)別從RR調(diào)整為RC,可以避免掉很多因?yàn)間ap鎖造成的死鎖啃奴。

5)為表添加合理的索引潭陪。可以看到如果不走索引將會(huì)為表的每一行記錄添加上鎖最蕾,死鎖的概率大大增大依溯。


顯式鎖 與 隱式鎖


隱式鎖:我們上文說(shuō)的鎖都屬于不需要額外語(yǔ)句加鎖的隱式鎖。

顯示鎖

SELECT ... LOCK IN SHARE MODE(加共享鎖);

SELECT ... FOR UPDATE(加排他鎖);

詳情上文已經(jīng)說(shuō)過(guò)瘟则。

通過(guò)如下sql可以查看等待鎖的情況

select * from information_schema.innodb_trx where trx_state="lock wait";

show engine innodb status;

mysql中的事務(wù)

show variables like "autocommit";

set autocommit=0; //0表示AutoCommit關(guān)閉

set autocommit=1; //1表示AutoCommit開啟

自動(dòng)提交(AutoCommit黎炉,mysql默認(rèn))

mysql默認(rèn)采用AutoCommit模式,也就是每個(gè)sql都是一個(gè)事務(wù)醋拧,并不需要顯示的執(zhí)行事務(wù)慷嗜。

如果autoCommit關(guān)閉,那么每個(gè)sql都默認(rèn)開啟一個(gè)事務(wù)丹壕,只有顯式的執(zhí)行“commit”后這個(gè)事務(wù)才會(huì)被提交

如果對(duì)java微服務(wù)庆械、分布式、高并發(fā)菌赖、高可用缭乘、大型互聯(lián)網(wǎng)架構(gòu)技術(shù)、面試經(jīng)驗(yàn)交流等等感興趣的同學(xué)盏袄,可以關(guān)注我忿峻,我會(huì)不定期免費(fèi)發(fā)放資料鏈接,如果你有好的學(xué)習(xí)資料可以私聊發(fā)我辕羽,我會(huì)注明出處之后分享給大家逛尚。歡迎分享,歡迎評(píng)論刁愿,歡迎轉(zhuǎn)發(fā)绰寞,需要資料的同學(xué)加入Java后端技術(shù)群:819940388,或關(guān)注微信公眾號(hào):Java資訊庫(kù)铣口,回復(fù)“架構(gòu)”滤钱,免費(fèi)的大型互聯(lián)網(wǎng)Java技術(shù)視頻分享給大家。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末脑题,一起剝皮案震驚了整個(gè)濱河市件缸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌叔遂,老刑警劉巖他炊,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件争剿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡痊末,警方通過(guò)查閱死者的電腦和手機(jī)蚕苇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)凿叠,“玉大人涩笤,你說(shuō)我怎么就攤上這事『屑” “怎么了蹬碧?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)炒刁。 經(jīng)常有香客問(wèn)我锰茉,道長(zhǎng),這世上最難降的妖魔是什么切心? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任飒筑,我火速辦了婚禮,結(jié)果婚禮上绽昏,老公的妹妹穿的比我還像新娘协屡。我一直安慰自己,他們只是感情好全谤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布肤晓。 她就那樣靜靜地躺著,像睡著了一般认然。 火紅的嫁衣襯著肌膚如雪补憾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天卷员,我揣著相機(jī)與錄音盈匾,去河邊找鬼。 笑死毕骡,一個(gè)胖子當(dāng)著我的面吹牛削饵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播未巫,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼窿撬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了叙凡?” 一聲冷哼從身側(cè)響起劈伴,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎握爷,沒想到半個(gè)月后跛璧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苏遥,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年赡模,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片师抄。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡漓柑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出叨吮,到底是詐尸還是另有隱情辆布,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布茶鉴,位于F島的核電站锋玲,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏涵叮。R本人自食惡果不足惜惭蹂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望割粮。 院中可真熱鬧盾碗,春花似錦、人聲如沸舀瓢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)京髓。三九已至航缀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間堰怨,已是汗流浹背芥玉。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留备图,地道東北人飞傀。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像诬烹,于是被迫代替她去往敵國(guó)和親砸烦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容