事務(Transaction)是訪問和更新數據庫的程序執行單元;事務中可能包含一個或多個 sql 語句,這些語句要麼都執行,要麼都不執行。
讀到其它事務爲提交的數據mysql
同一個事務,select語句相同但讀到數據不一樣sql
同一個事務,select語句項目但讀到數據行數不一樣
不可重複讀的重點是修改,幻讀的重點在於新增或者刪除。數據庫
一個事務中,能夠讀取到其餘事務未提交的變動併發
一個事務中,能夠讀取到其餘事務已經提交的變動性能
一個事務中,直到事務結束前,均可以反覆讀取到事務剛開始看到的數據,不會發生變化
mysql的默認隔離級別是RR
RR和RC的區別是在一個事務中RR隔離級別的讀到一張表的數據都是同樣學習
即使每次讀都須要得到表級共享鎖,每次寫都加表級排它鎖,兩個會話間讀寫會相互阻塞,會致使MySQL性能下降。spa
查看隔離級別:線程
SELECT @@tx_isolation;
事務ACID特性是如何實現的哪?日誌
事務的原子性、隔離性、持久性都是爲了實現數據一致性
InnoDB實現事務的回滾靠的就是undo_log
對數據進行修改會追加undo_log
對數據庫的修改並不會當即修改磁盤中的數據表,而是先追加redo_log,再更新內存中數據(Write-ahead
logging,預寫式日誌),後續由master thread或者刷髒線程階段性將這些數據刷到磁盤
這樣階段性的刷髒能夠將多個IO merge成一個IO,也下降了訪問延時,提供系統吞吐,當MySQL忽然宕機也不會致使數據丟失,可根據redo_log進行數據恢復
嚴格的隔離性對應Serializable(可串性化)隔離級別,在實際使用處於性能的考慮不多使用。
隔離性追求的是併發狀況下事務之間互補影響
在對數據進行修改時,須要得到鎖,在數據修改爲功事務提交以後釋放鎖
MySQL有行鎖和表鎖,InnoDB使用的行鎖,行鎖比表鎖鎖定更少的資源,在大部分狀況的性能更高
模擬併發更新致使死鎖的狀況:
在一個窗口鏈接mysql並執行如下操做code
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> update tuser set age=20 where id_card=4; Query OK, 0 rows affected (0.12 sec) Rows matched: 0 Changed: 0 Warnings: 0
另外一個窗口鏈接mysql並執行
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> update tuser set age=20 where id_card=4;
查看鎖狀況
mysql> select * from information_schema.innodb_locks; +-----------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+-----------+ | lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data | +-----------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+-----------+ | 2150479:671:3:2 | 2150479 | X | RECORD | `test`.`tuser` | PRIMARY | 671 | 3 | 2 | 1 | | 2150478:671:3:2 | 2150478 | X | RECORD | `test`.`tuser` | PRIMARY | 671 | 3 | 2 | 1 | +-----------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+-----------+ 2 rows in set, 1 warning (0.08 sec)
mysql> show engine innodb status;
Multi-Version Concurrency Control,即多版本的併發控制協議
MVCC解決了髒讀、不可重複讀、幻讀
MVCC,多個版本的數據能夠共存,主要是依靠數據的隱藏列(也能夠稱之爲標記位)和 undo log。
每行數據都會多2列
create_time系統版本號
delete_time系統版本號
select
1.判斷create_time, 行的系統版本號 <= 當前事務的系統版本號 2.判斷delete_time, 行的刪除版本未定義 || 大於當前事務版本號
update
插入一條新紀錄,更新create_time 刪除一條數據,並更新delete_time
insert
更新create_time
delete
更新delete_time
1.事務A執行begin開啓事務,select查詢時向系統申請一個版本號
2.事務B執行update更新了tuser表中id=4這一行數據的版本號
3.事務A select查詢使用的仍是第一次select時使用的版本號,判斷id=4這一行的版本號比當前版本號大,經過undo_log找到和當前版本號一致的數據,事務A二次查詢結果時一致的,實現了事務的可重複讀
MySQL做爲一個開源數據庫,被不少公司使用,在使用過程當中去深刻了解其內部原理是頗有必要的事情,知其然並知其因此然,學習是一個積累的過程,只要堅持就會有收穫。