數據庫併發控制和日誌管理
---------------------------------------------------------------------------------------------------------------------------------------------
1、併發控制
(2)讀鎖:共享鎖,只讀不可寫,多個讀取互不阻塞,意思是多臺主機可以同時查看一張上了讀鎖的表
寫鎖:獨佔鎖、排它鎖,一個寫鎖會阻塞其它讀和寫鎖,當A用戶對錶上寫鎖,其他用戶對該表不能讀,更不能寫
LOCK TABLES tblname {READ | WRITE}:加鎖
FLUSH TABLES TBNAME:關閉正在打開的表,在備份前加全局讀鎖,如果不指定表明,全部數據庫全部表格都將加入讀鎖,適用於溫備分
SELECT...WHERE從句 FOR UPDATE:加寫鎖
SELECT...WHERE從句 LOCK IN SHARE MODE:加讀鎖
(4)實現
(1)事務Transactions:一組原子性的SQL語句,或一個獨立動作單元
(2)事務日誌:記錄事務信息,實現undo,redo等故障恢復功能
A:atomicity,原子性,整個事務中的所有操作要麼全部成功執行,要麼全部失敗後回滾
C:consistency一致性,數據庫總是從一個一致性狀態轉換爲另一個一致性狀態
I:isolation隔離性,一個事務所做出的操作在提交之前,不能被其它事務所見,隔離有多種隔離級別,實現併發
D:durability持久性,一旦事務提交,其所做的修改會永久保存於數據庫中
BEGIN、BEGIN WORK\START TRANSACTION
注:只有事務型存儲引擎中的DML語句方能支持此類操作,即增刪改操作
(3)自動提交:set autocommit={1|0},默認爲1,爲0時設爲手動提交
mysql和sql server默認設置是自動提交,oracle默認手動提交
網站查詢結果是--autocommit, autocommit,表明選項和變量都有
ROLLBACK [WORK] TO [SAVEPOINT] identifier
注意:savepoint保存點名稱必須字母開頭,不可以是純數字
提交後
事務保存點示例:先有以下結果產生
此時後悔了,想把數據表恢復到savepoint sp2處,也就是sp2點完菜,但未做sp3點,結果如圖
<1>READ UNCOMMITTED 可讀取到未提交數據,產生髒讀
<2>READ COMMITTED 可讀取到提交數據,但未提交數據不可讀,產生不可重複讀,即可讀取到多個提交數據,導致每次讀取數據不一致
<3>REPEATABLE READ 可重複讀,多次讀取數據都一致,產生幻讀,即讀取過程中,即使有其它提交的事務修改數據,仍只能讀取到未修改前的舊數據。此爲MySQL默認設置,意思是修改記錄過程中表格對其他用戶產生行鎖,事務完成提交後纔對其他用戶顯示修改後的數據
<4>SERIALIZABILE 可串行化,未提交的讀事務阻塞修改事務,或者未提交的修改事務阻塞讀事務。導致併發性能差
事務隔離級別 | 髒讀可能性 | 不可重複讀 可能性 | 幻讀可能性 | 加鎖讀 |
讀未提交(read-uncommitted) | Y | Y | Y | N |
不可重複讀(read-committed) | N | Y | Y | N |
可重複讀(repeatable-read) | N | N | Y | N |
串行化(serializable) | N | N | N | Y |
transaction-isolation=SERIALIZABLE
6、併發控制
(1)死鎖:兩個或多個事務在同一資源相互佔用,並請求鎖定對方佔用的資源的狀態
(2)事務日誌的寫入類型爲“追加”,因此其操作爲“順序IO”;通常也被稱爲:預寫式日誌 write ahead logging,條件允許可以將事務日誌獨立放入一個硬盤分區中,使得事務日誌的寫入不用隨便插入地方進行寫入而是追加
日誌文件: ib_logfile0, ib_logfile1,位於數據庫存放目錄下,可以更
(1)show processlist \G
(2)看到數據庫進程後確定結束阻塞的id號,比如5號,輸入kill 5
8、日誌
(1)當對一個表格刪除大量數據後,它的日誌文件不會縮小,此時需要優化表格,執行命令:optimize table TBLNAME,使得該表的日誌文件容量縮小
<1>日誌
<2>二進制日誌,因爲非常重要,內容又多,所以單獨放一分類
mysqlbinlog [OPTIONS] log_file...
示例:mysqlbinlog --start-position=1465 --stop-position=2123 mysql-bin.000001
<4>清除指定二進制日誌
PURGE { BINARY | MASTER } LOGS
{ TO 'log_name' | BEFORE datetime_expr }
PURGE BINARY LOGS TO ‘mariadb-bin.000003’;刪除3之前的日誌
PURGE BINARY LOGS BEFORE '2017-01-23';
PURGE BINARY LOGS BEFORE '2017-03-22 09:25:30';
RESET MASTER [TO #]; 日誌文件從#開始記數,默認從1開始,一般是master第一次啓動時執行,MariaDB10.1.6開始支持TO #