MySql事務和鎖

MySql事務

1 數據庫事務種類

1.1 事務的幾大原則

  1. 原子性 Automicity
  2. 一致性 Consistency
  3. 隔離性 Isolation
  4. 持久性 Durability

1.2 數據庫事務分類

  1. 讀未提交: 一個事務還沒提交時,它作的變動就能被其餘事務看到。
  2. 讀提交(read commit): 一個事務提交後,才能被別的事務看到。
  3. 可重複一個事務執行過程當中看到的事務,老是和這個數據啓動時看到的數據是一致的。本事務未提交的變動也是不可讀的。
  4. 串行化對同一行記錄,寫會加鎖,讀也會加鎖,後一個操做必定要等到前一個操做完成。

並行性能依次下降,安全性依次提升。mysql

時間T1 時間T2 時間T2 時間T3 時間T4 時間T5 時間T6 時間T7
事務A 啓動事務 讀取值1 讀取值V1 讀取值V2 提交事務A 讀取值V3
事務B 啓動事務 讀取值1 修改值爲2 提交事務B

讀未提交那麼V一、V二、V3值都是2。sql

讀提交那麼V1爲1,V2和V3是2。數據庫

可重複那麼V1和V2都是1,V3是2。安全

串行化事務A執行完後執行事務B,而後讀取值。因此V1和V2是1,V3是2。工具

1.3 爲何建議不使用長事務

長事務意味着數據會保留不少老的事務視圖,這些事務視圖是爲了方便事務的回滾。因爲事務隨時均可能回滾,因此數據庫須要使用存儲空間進行保存。性能

在mysql5.5以前的版本,回滾日誌和數據字典放在一塊兒,即便事務提交了,回滾段被清理,空間也不會變小。致使最後爲了清理空間,只好將整個庫給重建。線程

數據參數autocommit=0表示,不自動提交;建議將autocommit值設置1,這樣就能夠儘可能避免長事務。下面這個語句用於查詢事務時間超過120s的。日誌

select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>120orm

避免長事務:一、業務鏈接數據庫時,經過設置set max_execute_time來控制長事務。二、設置set autocommit=1。事務

2 數據庫鎖分類

數據庫鎖能夠分爲全局鎖,表鎖,行鎖。

2.1 全局鎖

全局鎖是對整個數據庫實例加鎖。MySQL 提供了一個加全局讀鎖的方法,命令是

Flush tables with read lock

(FTWRL)。當你須要讓整個庫處於只讀狀態的時候,可使用這個命令,以後其餘線程的如下語句會被阻塞:數據更新語句(數據的增刪改)、數據定義語句(包括建表、修改表結構等)和更新類事務的提交語句。

全局鎖是在作全局備份的時候使用。若是你在主庫上備份,那麼在備份期間都不能執行更新,業務基本上就得停擺。官方自帶的邏輯備份工具是 mysqldump。當 mysqldump 使用參數–single-transaction 的時候,導數據以前就會啓動一個事務,來確保拿到一致性視圖。single-transaction 方法只適用於全部的表使用事務引擎的庫。若是有的表使用了不支持事務的引擎,那麼備份就只能經過 FTWRL 方法。這每每是 DBA 要求業務開發人員使用 InnoDB 替代 MyISAM 的緣由之一。

2.2 表級別鎖

MySQL 裏面表級別的鎖有兩種:一種是表鎖,一種是元數據鎖(meta data lock,MDL)。

舉個例子若是在某個線程 A 中執行 lock tables t1 read, t2 write; 這個語句,則其餘線程寫 t一、讀寫 t2 的語句都會被阻塞。同時,線程 A 在執行 unlock tables 以前,也只能執行讀 t一、讀寫 t2 的操做。連寫 t1 都不容許,天然也不能訪問其餘表。

MDL 不須要顯式使用,在訪問一個表的時候會被自動加上。MDL 的做用是,保證讀寫的正確性。你能夠想象一下,若是一個查詢正在遍歷一個表中的數據,而執行期間另外一個線程對這個表結構作變動,刪了一列,那麼查詢線程拿到的結果跟表結構對不上,確定是不行的。

如何安全地給小表加字段?

  1. 若是有常事務: 如今數據庫schema表查看常事務,而後中止。
  2. 若是操做的是一個熱表,數據使用頻繁alert table加等待時間,若是沒有鎖拿到,則放棄,而後重試。
相關文章
相關標籤/搜索