Mysql(三):鎖與事務

1.MySql中的鎖

  • 表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的概率最高,併發度最低。表級鎖更適合於以查詢爲主,只有少量按索引條件更新數據的應用,如 OLAP (Online analytical processing,聯機分析處理)系統。
  • 行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。行級鎖則更適合於有大量按索引條件併發更新少量不同數據,同時又有併發查詢的應用,如一些OLTP(On-Line Transaction Processing:聯機事務處理)系統。
  • 頁面鎖(gap 鎖,間隙鎖):開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度一般。

2.MyISAM 鎖

表共享讀鎖(Table Read Lock)

  • 語法:lock table 表名 READ,unlock tables;解鎖
lock table testmysam READ 
  • 讀鎖,對 MyISAM 表的讀操作,不會阻塞當前 session/其他session對同一表的讀請求,但會阻塞對同一表的寫請求;當前session更新或訪問讀其他表都會提示錯誤(查詢被鎖的表不能使用別名,否則也會被鎖)

表獨佔寫鎖(Table Write Lock)

  • 語法:lock table 表名 WRITE;unlock tables;解鎖
lock table testmysam WRITE
  • 寫鎖,對 MyISAM 表的寫操作,則會阻塞其他會話對同一表的讀和寫操作,當前 session 可以對本表做 CRUD,但對其他表進行操作會報錯

3.InnoDB 鎖

共享鎖

  • 又稱讀鎖。當一個事務對某幾行上讀鎖時,允許其他事務對這幾行進行讀操作,但不允許其進行寫操作,也不允許其他事務給這幾行上排它鎖,但允許上讀鎖。

  • 語法:select * from 表where 條件lock in share mode;

排它鎖

  • 又稱寫鎖。當一個事務對某幾個上寫鎖時,不允許其他事務寫,但允許讀。更不允許其他事務給這幾行上任何鎖。
  • 語法:select * from 表where 條件for update;

注意

1.兩個事務不能鎖同一個索引的同一部分值,另一個等待。

2.insert ,delete , update 在事務中都會自動默認加上排它鎖。即使後面沒加for update

3.行鎖必須有索引才能實現,否則會自動鎖全表,那麼就不是行鎖了。

排查

查看鎖以及被鎖數據:

mysql5.6&mysql5.7:

select * from information_schema.INNODB_LOCKS;

Mysql8:

SELECT * from performance_schema.data_locks;

查看具體要kill的線程號:

mysql5.7&mysql8:

select * from sys.innodb_lock_waits;

mysql5.6:

SELECT
r.trx_id waiting_trx_id,r.trx_mysql_thread_id waiting_thread,
r.trx_query waiting_query,
b.trx_id blocking_trx_id,
b.trx_mysql_thread_id blocking_thread
FROM
information_schema.innodb_lock_waits w
INNER JOIN
information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
INNER JOIN
information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;

4.查看支持事務的存儲引擎

show engines; --只有InnoDB

show variables like '%storage_engine%'; --查看默認存儲引擎

show create table 表名; --查看某張表使用的存儲引擎

5.事務特性

原子性(atomicity)

一個事務必須被視爲一個不可分割的最小單元,整個事務中的所有操作要麼全部提交成功,

要麼全部失敗,對於一個事務來說,不可能只執行其中的一部分操作

一致性(consistency)

一致性是指事務將數據庫從一種一致性轉換到另外一種一致性狀態,在事務開始之前和事務

結束之後數據庫中數據的完整性沒有被破壞

持久性(durability)

一旦事務提交,則其所做的修改就會永久保存到數據庫中。此時即使系統崩潰,已經提交的

修改數據也不會丟失

隔離性(isolation)

一旦事務提交,則其所做的修改就會永久保存到數據庫中。此時即使系統崩潰,已經提交的

修改數據也不會丟失

  • 未提交讀(READ UNCOMMITED)髒讀
  • 已提交讀(READ COMMITED)不可重複讀
  • 可重複讀(REPEATABLE READ)
  • 可串行化(SERIALIZABLE)
show variables like '%tx_isolation%'; --默認RR可重複讀

未提交讀(READ UNCOMMITED)

會引起髒讀,不可重複讀,幻讀

set SESSION TRANSACTION ISOLATION LEVEL read UNCOMMITTED;

已提交讀(READ COMMITED)

解決髒讀,會引起不可重複讀,幻讀

set SESSION TRANSACTION ISOLATION LEVEL read committed;

可重複讀(REPEATABLE READ)

解決不可重複讀,會引起幻讀

mysql默認隔離級別,通過間隙鎖解決幻讀問題

set SESSION TRANSACTION ISOLATION LEVEL repeatable read;

可串行化(SERIALIZABLE)

解決幻讀

set SESSION TRANSACTION ISOLATION LEVEL serializable;

間隙鎖(gap鎖)

select @@tx_isolation;

create table t_lock_1 (a int primary key);

insert into t_lock_1 values(10),(11),(13),(20),(40);

對於主鍵索引

一個會話中:

begin;

select * from t_lock_1 where a <= 13 for update;

另一個會話中

insert into t_lock_1 values(21) --成功

insert into t_lock_1 values(19) --阻塞

where id <=x for update;

mysql5.7中:掃描到值x在表中的下一個值爲止,都不可改,(-無窮,下一個值]

mysql8中:掃描到當前值x 都不可改

where id in (a,b) for update;

mysql5.7中:整張表不可改

Mysql8.0中:只有in條件中的數據不可改

非主鍵上的索引:

create table t_lock_2 (a int primary key,b int, key (b));

insert into t_lock_2 values(1,1),(3,1),(5,3),(8,6),(10,8);

一個會話中:

BEGIN;

select * from t_lock_2 where b=3 for update;

另一個會話中:

select * from t_lock_2 where a = 5 lock in share mode; -- 不可執行,因爲a=5 上有一把記錄鎖

insert into t_lock_2 values(4, 2); -- 不可以執行,因爲b=2 在(1, 3]內

insert into t_lock_2 values(6, 5); -- 不可以執行,因爲b=5 在(3, 6)內

insert into t_lock_2 values(2, 0); -- 可以執行,(2, 0)均不在鎖住的範圍內

insert into t_lock_2 values(6, 7); -- 可以執行,(6, 7)均不在鎖住的範圍內

insert into t_lock_2 values(9, 6); -- 可以執行

insert into t_lock_2 values(7, 6); -- 不可以執行


鎖住值x對應的主鍵id對應不可改

非主鍵索引鎖得是[上一個值,下一個值]

6.事務語法

開啓事務

begin;
START TRANSACTION;
begin work;

事務回滾

rollback;

事務提交

commit;

還原點

savepoint

show variables like '%autocommit%'; --自動提交事務是開啓的

set autocommit=0;

insert into testdemo values(5,5,5);

savepoint s1;

insert into testdemo values(6,6,6);

savepoint s2;

insert into testdemo values(7,7,7);

savepoint s3;

select * from testdemo

rollback to savepoint s2

rollback
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章