事務就是一組一起成功或一起失敗的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 讀已提交 保證乙個事務修改的資料提交後才能被另外乙個事務讀取。另外乙...