1
mysql
事務是數據庫操做的最小工做單元,是做爲單個邏輯工做單元執行的一系列操做,這些操做做爲一個總體一塊兒向系統提交,要麼都執行、要麼都不執行,是一組不可再分割的操做集合。sql
通俗理解就是作一件事情的過程,事務封裝了一條dml、或者多條dml語句。這個過程有兩種結果:要麼所有成功、要麼所有失敗。數據庫
C=Consistency ,一致性:系統老是從一個一致性的狀態轉移到另外一個一致性的狀態。例如從 A 帳戶轉帳到 B 帳戶,不能由於 A 帳戶扣了錢,而 B 帳戶沒有加錢,不管 A 和 B 怎麼轉帳,系統中總額是固定的。若是數據庫系統運行中發生故障,有些事務還沒有完成就被迫中斷,這些未完成事務對數據庫所作的修改有一部分已寫入物理數據庫,這時數據庫就處於一種不正確的狀態,或者說是不一致的狀態。服務器
I=Isolation ,隔離性: 一般來講一個事務在徹底提交以前,對其餘事務是不可見的。也就是說,不一樣的事務併發操做相同的數據時,每一個事務都有各自完整的數據空間。一個事務內部的操做及使用的數據對其它併發事務是隔離的,併發執行的各個事務是不能互相干擾的。網絡
D=Durability ,持久性:事務一旦提交,將永久存在,接下來的其它操做或故障不該該對其執行結果有任何影響。即便服務器系統崩潰或服務器宕機等故障。只要數據庫從新啓動,那麼必定可以將其恢復到事務成功結束後的狀態。併發
MySQL 的隔離等級對加鎖有影響,因此在分析具體加鎖場景時,首先要肯定當前的隔離等級,分爲如下幾個等級:ide
讀未提交(Read Uncommitted ,簡稱 RU):能夠讀到未提交的讀,基本上不會使用該隔離等級,因此暫時忽略。函數
讀已提交(Read Committed ,簡稱 RC):存在幻讀問題,對當前讀獲取的數據加記錄鎖。高併發
可重複讀(Repeatable Read ,簡稱 RR):不存在幻讀問題,對當前讀獲取的數據加記錄鎖,同時對涉及的範圍加間隙鎖,防止新的數據插入,致使幻讀。優化
序列化(Serializable):從 MVCC 併發控制退化到基於鎖的併發控制,不存在快照讀,都是當前讀,併發效率急劇降低,不建議使用。
隔離級別與對應問題矩陣以下所示:
隔離級別 |
髒讀 |
不可重複讀 |
幻讀 |
讀未提交 |
是 |
是 |
是 |
不可重複讀 |
否 |
是 |
是 |
可重複讀 |
否 |
否 |
是(MySQL否) |
串行化 |
否 |
否 |
否 |
注,常見數據庫的默認級別:
MySQL 數據庫的默認隔離級別是 Repeatable read (可重複讀)級別。
Oracle數據庫中,只支持 Seralizable(順序讀) 和 Read committed(讀已提交)級別,默認的是 Read committed 級別。
SQL Server 數據庫中,默認的是 Read committed(讀已提交) 級別。
2個事務交叉:同一個事務中出現delete,insert操做;
3個insert事務,一個回滾:三個事務的 insert 語句都是insert ignore into t1(a, b)values("1", "1");
多個事務,間隙鎖形成死鎖:同一個事務中多個update操做致使鎖升級(行鎖升級爲表鎖),併發操做時會致使死鎖;
drop:drop是DDL,會隱式提交,因此,不能回滾,不會觸發觸發器;drop語句刪除表結構及全部數據,並將表所佔用的空間所有釋放,底層系統文件會變小;drop語句將刪除表的結構所依賴的約束,觸發器,索引,依賴於該表的存儲過程/函數將保留,可是變爲invalid狀態。
truncate:truncate是DDL,會隱式提交,因此,不能回滾,不會觸發觸發器;truncate會刪除表空間,底層系統文件會變小。而且將從新設置高水線和全部的索引,缺省狀況下將空間釋放到minextents個extent,除非使用reuse storage。不會記錄日誌,因此執行速度很快,但不能經過rollback撤消操做,若是一不當心把一個表truncate掉,也是能夠恢復的,只是不能經過rollback來恢復;對於外鍵(foreignkey )約束引用的表,不能使用 truncate table,而應使用不帶 where 子句的 delete 語句;truncatetable不能用於參與了索引視圖的表。
delete:delete是DML,執行delete操做時,每次從表中刪除一行,而且同時將該行的的刪除操做記錄在redo和undo表空間中以便進行回滾(rollback)和重作操做,但要注意表空間要足夠大,須要手動提交(commit)操做才能生效,能夠經過rollback撤消操做;delete可根據條件刪除表中知足條件的數據,若是不指定where子句,那麼刪除表中全部記錄,只刪表數據,刪除操做後,底層系統文件不會變小;delete語句不影響表所佔用的extent,高水線(high watermark)保持原位置不變。
總結:
在速度上,通常來講,drop> truncate > delete。
在使用drop和truncate時必定要注意,雖然能夠恢復,但爲了減小麻煩,仍是要慎重。
若是想刪除部分數據用delete,注意帶上where子句,回滾段要足夠大;若是想刪除表,用drop; 若是想保留表而將全部數據刪除,若是和事務無關,用truncate便可;若是和事務有關,或者想觸發trigger,仍是用delete; 若是是整理表內部的碎片,能夠用truncate跟上reuse stroage,再從新導入/插入數據。
索引大大減少了服務器須要掃描的數據量;
索引能夠幫助服務器避免排序和臨時表;
索引能夠將隨機IO變成順序IO;
類型轉換:當存在索引列的數據類型隱形轉換,則用不上索引,好比列類型是字符串,那必定要在條件中將數據使用引號引用起來,不然不使用索引;
索引列加函數:加了函數沒法使用上索引;
字符校對規則不對;
沒有索引或者沒有用到索引(這是查詢慢最多見的問題,是程序設計的缺陷);
沒有建立計算列致使查詢不優化;
查詢出的數據量過大(能夠採用屢次查詢或其餘方法下降數據量);
查詢語句須要優化;