mysql的事務,隔離級別和鎖用法例項分析

2022-09-25 01:57:08 字數 3503 閱讀 9006

事務就是一組一起成功或一起失敗的sql語句。事務還應該具備,原子性,一致性,隔離性和永續性。

一、事務的基本要素 (acid)

1、原子性:事務開始後,所有的操作,要麼全部成功,要麼全部失敗,不可能處於中間狀態,事務是乙個不可分割的整體,就像原子一樣。

2、一致性:事務開始前和結束後,資料庫的完整性約束沒有破壞,a向b轉賬,a扣了錢,但b卻沒到賬。

3、隔離性:同時發生的事務(併發事務)不應該導致資料庫處於不一致的狀態中,每個事務都獨立執行,不影響其他事務的存在。

4、永續性:事務對資料庫的更改都會儲存在磁碟上,不會丟失。

二、事務的併發問題

1、髒讀:事務a讀取了事務b未提交的寫入資料,讀取到的資料就稱為髒資料

2、不可重複讀:事務a多次讀取同一資料,但在讀取過程中,事務b對資料做了修改,並提交了。導致多次讀取同一資料,結果不一樣。

3、幻讀:事務a對錶中所有資料行進行了修改,比如設定status = 1,但同時,事務b往該錶插入了一行新資料status = 0,對於操作事務a的使用者而言,表中還有一條記錄沒被修改,就像發生幻覺一樣。

三、事務隔離性的四個級別

事務隔離級別

髒讀不可重複讀

幻讀讀取未提交 read uncommitted

讀已提交 read committed

可重複讀取 repeatable read

序列化 serializable

四、獲取和設定資料庫隔離級別

show variables like www.cppcns.com'%isolation%';

show global variables like '%isolation%';

使用系統變數查詢

select @@global.tx_isolation;

select @@session.tx_isolation;

select @@tx_isolation;

對於mysql8而言,使用下面的變數進行查詢

select @@global.transaction_isolation;

@@session.transaction_isolation;

select @@trawww.cppcns.comnsaction_isolation;

設定隔離級別

set global tx_isolation = '隔離級別';

set session tx_isolation = '隔離級別';

set @@tx_isolation = '隔離級別';

對於mysql8而言,使用下面語句進行設定

set global transaction_isolation = '隔離級別';

set session transaction_isolation = '隔離級別';

set @@transaction_isolation = '隔離級別';

五、通過例子說明各隔離級別的情況

先準備一張表,和一點資料。

create table `account` (

`id` int(11) unsigned not null auto_increment comment 'id',

`name` varchar(32) default '' comment '名稱',

`money` decimal(11,2) default '0.00' comment '金錢',

primary key (`id`)

) engine=innodb default charset=utf8mb4;

insert into `account` (`name`, `money`) values ('a', '500.00');

insert into `accoun程式設計客棧t` (`name`, `money`) values ('b', '100.00');

1、讀取未提交

set transaction_isolation = 'read-uncommitted';

set autocommit = 0;

事務b修改了表中的資料,但是未提交,事務a確讀取到了修改後的資料。如果因為某些原因,事務b回滾了,事務a讀取的這個資料就是髒資料。

2、讀已提交

set transaction_isolation = 'read-committed';

set autocommit = 0;

事務b修改資料但沒有提交,那麼事務a仍然獲取的原來資料,解決了髒讀的問題。

但是事務b提交,事務a執行上一次查詢,結果與上一次查詢不一致,這就產生不可重複讀的問題。

3、可重複讀取

set transaction_isolation = 'repeatable-read';

set autocommit = 0;

事務b修改了資料並提交了,事務a兩次查詢的結果是一致的,解決了不可重複讀的問題。

這個時候,事務a去修改name為a的money資料

name為a的money變成了350,而不是400,可重複讀保證了資料的一致性。

我們重新在事務a中修改所有賬號的money等於200,同時在事務b中插入一條新的資料。

事務a中獲取的仍然是兩條資料,解決了新增資料時,事務a出現的幻讀問題。

4、序列化

set transaction_isolation = 'serializable';

set autocommit = 0;

事務a對錶進行查詢,如果沒有提交,則事務b的插入語句一直等待在那裡,直到超時或事務a提交。

反之,事務b對錶進行插入後,沒有提交,則事務a對錶的查詢也一直等待,直到事務b提交。

此時對錶的讀寫都會進行鎖表,當然對併發效能的影響也比較大。

隔離級別越高,越能保證資料的完整性和一致性。

六、mysql的鎖

鎖分程式設計客棧為兩種型別:

內部鎖:mysql伺服器內部執行的內部鎖,以管理多個會話對錶內容的爭用。

外部鎖:mysql為客戶會話提供顯式地獲取表鎖,以阻止其他會話訪問表。

內部鎖又會為兩種型別:

1、行級鎖:行級鎖是細粒度的,只有被訪問的行會被鎖定,這允許多個會話同時進行寫訪問。

2、表級鎖:mysql對myisam,memory和merge表使用表級鎖,一次只允許乙個會話更新表,這使得這些儲存引擎更適用於以讀取為主的操作。

外部鎖:可以使用 lock table 和 unlock table 來控制鎖定。

read (共享鎖) :多個會話可以從表中讀取資料而不需要獲取鎖,此外,多個會話可以在同一表上獲得鎖,當 read 鎖時,沒有會話可以將資料寫入表中。任何寫入操作都將處於等待狀態,直到 read 鎖被釋放。

write (排他鎖) :當表被 write 鎖定時,除持有該鎖的會話外,其他會話都不能讀取或寫入資料,除非 write 鎖被釋放。

鎖表的語句:

lock tables table_name [read | write];

解鎖表的語句:

unlock tables;

鎖定資料庫中所有表:

flush tables with read lock;

MySQL的事務隔離級別和鎖

mysql的事務隔離級別 read uncommitted 讀未提交資料 read committed 讀已提交資料 repeatable read 可重讀 serializable 可序列化 檢視mysql的事務隔離級別 預設 全域性和會話事務隔離級別 select tx isolation se...

mysql 鎖 事務隔離級別

最近在看mysql相關的書籍.實驗了一些內容.分享一下,主要是關於事務隔離級別 read committed和repeatable read 和鎖相關的.很多網上文章上都能搜尋到 read committed可以防止髒資料.但是不能防止 不可重複讀.而repeatable read可以防止 不可重複...

Mysql事務隔離級別和鎖機制

一.spring支援四種事務隔離級別 1.isolation read uncommitted 讀未提交 這是事務最低的隔離級別,它充許令外乙個事務可以看到這個事務未提交的資料。2.isolation read committed 讀已提交 保證乙個事務修改的資料提交後才能被另外乙個事務讀取。另外乙...