mysql數據庫入門知識點(數據庫mysql知識點整理)

本文目錄一覽:

MySQL知識點總結

只要字段值還可以繼續拆分,就不滿足第一範式。

範式設計得越詳細,對某些實際操作可能會更好,但並非都有好處,需要對項目的實際情況進行設定。

在滿足第一範式的前提下,其他列都必須完全依賴於主鍵列。 如果出現不完全依賴,只可能發生在聯合主鍵的情況下:

實際上,在這張訂單表中,product_name 只依賴於 product_id ,customer_name 只依賴於 customer_id。也就是說,product_name 和 customer_id 是沒用關係的,customer_name 和 product_id 也是沒有關係的。

這就不滿足第二範式:其他列都必須完全依賴於主鍵列!

拆分之後,myorder 表中的 product_id 和 customer_id 完全依賴於 order_id 主鍵,而 product 和 customer 表中的其他字段又完全依賴於主鍵。滿足了第二範式的設計!

在滿足第二範式的前提下,除了主鍵列之外,其他列之間不能有傳遞依賴關係。

表中的 customer_phone 有可能依賴於 order_id 、 customer_id 兩列,也就不滿足了第三範式的設計:其他列之間不能有傳遞依賴關係。

修改後就不存在其他列之間的傳遞依賴關係,其他列都只依賴於主鍵列,滿足了第三範式的設計!

查詢每門課的平均成績。

查詢 score 表中至少有 2 名學生選修,並以 3 開頭的課程的平均分數。

分析表發現,至少有 2 名學生選修的課程是 3-105 、3-245 、6-166 ,以 3 開頭的課程是 3-105 、3-245。也就是說,我們要查詢所有 3-105 和 3-245 的 degree 平均分。

查詢所有學生的 name,以及該學生在 score 表中對應的 c_no 和 degree 。

通過分析可以發現,只要把 score 表中的 s_no 字段值替換成 student 表中對應的 name 字段值就可以了,如何做呢?

查詢所有學生的 no 、課程名稱 ( course 表中的 name ) 和成績 ( score 表中的 degree ) 列。

只有 score 關聯學生的 no ,因此只要查詢 score 表,就能找出所有和學生相關的 no 和 degree :

然後查詢 course 表:

只要把 score 表中的 c_no 替換成 course 表中對應的 name 字段值就可以了。

查詢所有學生的 name 、課程名 ( course 表中的 name ) 和 degree 。

只有 score 表中關聯學生的學號和課堂號,我們只要圍繞着 score 這張表查詢就好了。

只要把 s_no 和 c_no 替換成 student 和 srouse 表中對應的 name 字段值就好了。

首先把 s_no 替換成 student 表中的 name 字段:

再把 c_no 替換成 course 表中的 name 字段:

查詢 95031 班學生每門課程的平均成績。

在 score 表中根據 student 表的學生編號篩選出學生的課堂號和成績:

這時只要將 c_no 分組一下就能得出 95031 班學生每門課的平均成績:

查詢在 3-105 課程中,所有成績高於 109 號同學的記錄。

首先篩選出課堂號為 3-105 ,在找出所有成績高於 109 號同學的的行。

查詢所有成績高於 109 號同學的 3-105 課程成績記錄。

查詢所有和 101 、108 號學生同年出生的 no 、name 、birthday 列。

查詢 ‘張旭’ 教師任課的學生成績表。

首先找到教師編號:

通過 sourse 表找到該教師課程號:

通過篩選出的課程號查詢成績表:

查詢某選修課程多於5個同學的教師姓名。

首先在 teacher 表中,根據 no 字段來判斷該教師的同一門課程是否有至少5名學員選修:

查看和教師編號有有關的表的信息:

我們已經找到和教師編號有關的字段就在 course 表中,但是還無法知道哪門課程至少有5名學生選修,所以還需要根據 score 表來查詢:

根據篩選出來的課程號,找出在某課程中,擁有至少5名學員的教師編號:

在 teacher 表中,根據篩選出來的教師編號找到教師姓名:

查詢 “計算機系” 課程的成績表。

思路是,先找出 course 表中所有 計算機系 課程的編號,然後根據這個編號查詢 score 表。

查詢 計算機系 與 電子工程系 中的不同職稱的教師。

查詢課程 3-105 且成績 至少 高於 3-245 的 score 表。

查詢課程 3-105 且成績高於 3-245 的 score 表。

查詢某課程成績比該課程平均成績低的 score 表。

查詢所有任課 ( 在 course 表裡有課程 ) 教師的 name 和 department 。

查詢 student 表中至少有 2 名男生的 class 。

查詢 student 表中不姓 “王” 的同學記錄。

查詢 student 表中每個學生的姓名和年齡。

查詢 student 表中最大和最小的 birthday 值。

以 class 和 birthday 從大到小的順序查詢 student 表。

查詢 “男” 教師及其所上的課程。

查詢最高分同學的 score 表。

查詢和 “李軍” 同性別的所有同學 name 。

查詢和 “李軍” 同性別且同班的同學 name 。

查詢所有選修 “計算機導論” 課程的 “男” 同學成績表。

需要的 “計算機導論” 和性別為 “男” 的編號可以在 course 和 student 表中找到。

建立一個 grade 表代表學生的成績等級,並插入數據:

查詢所有學生的 s_no 、c_no 和 grade 列。

思路是,使用區間 ( BETWEEN ) 查詢,判斷學生的成績 ( degree ) 在 grade 表的 low 和 upp 之間。

準備用於測試連接查詢的數據:

分析兩張表發現,person 表並沒有為 cardId 字段設置一個在 card 表中對應的 id 外鍵。如果設置了的話,person 中 cardId 字段值為 6 的行就插不進去,因為該 cardId 值在 card 表中並沒有。

要查詢這兩張表中有關係的數據,可以使用 INNER JOIN ( 內連接 ) 將它們連接在一起。

完整顯示左邊的表 ( person ) ,右邊的表如果符合條件就顯示,不符合則補 NULL 。

完整顯示右邊的表 ( card ) ,左邊的表如果符合條件就顯示,不符合則補 NULL 。

完整顯示兩張表的全部數據。

在 MySQL 中,事務其實是一個最小的不可分割的工作單元。事務能夠 保證一個業務的完整性 。

比如我們的銀行轉賬:

在實際項目中,假設只有一條 SQL 語句執行成功,而另外一條執行失敗了,就會出現數據前後不一致。

因此,在執行多條有關聯 SQL 語句時, 事務 可能會要求這些 SQL 語句要麼同時執行成功,要麼就都執行失敗。

在 MySQL 中,事務的 自動提交 狀態默認是開啟的。

自動提交的作用 :當我們執行一條 SQL 語句的時候,其產生的效果就會立即體現出來,且不能 回滾 。

什麼是回滾?舉個例子:

可以看到,在執行插入語句後數據立刻生效,原因是 MySQL 中的事務自動將它 提交 到了數據庫中。那麼所謂 回滾 的意思就是,撤銷執行過的所有 SQL 語句,使其回滾到 最後一次提交 數據時的狀態。

在 MySQL 中使用 ROLLBACK 執行回滾:

由於所有執行過的 SQL 語句都已經被提交過了,所以數據並沒有發生回滾。那如何讓數據可以發生回滾?

將自動提交關閉後,測試數據回滾:

那如何將虛擬的數據真正提交到數據庫中?使用 COMMIT :

事務的實際應用 ,讓我們再回到銀行轉賬項目:

這時假設在轉賬時發生了意外,就可以使用 ROLLBACK 回滾到最後一次提交的狀態:

這時我們又回到了發生意外之前的狀態,也就是說,事務給我們提供了一個可以反悔的機會。假設數據沒有發生意外,這時可以手動將數據真正提交到數據表中:COMMIT 。

事務的默認提交被開啟 ( @@AUTOCOMMIT = 1 ) 後,此時就不能使用事務回滾了。但是我們還可以手動開啟一個事務處理事件,使其可以發生回滾:

仍然使用 COMMIT 提交數據,提交後無法再發生本次事務的回滾。

事務的四大特徵:

事務的隔離性可分為四種 ( 性能從低到高 ) :

查看當前數據庫的默認隔離級別:

修改隔離級別:

測試 READ UNCOMMITTED ( 讀取未提交 ) 的隔離性:

由於小明的轉賬是在新開啟的事務上進行操作的,而該操作的結果是可以被其他事務(另一方的淘寶店)看見的,因此淘寶店的查詢結果是正確的,淘寶店確認到賬。但就在這時,如果小明在它所處的事務上又執行了 ROLLBACK 命令,會發生什麼?

這就是所謂的 臟讀 ,一個事務讀取到另外一個事務還未提交的數據。這在實際開發中是不允許出現的。

把隔離級別設置為 READ COMMITTED :

這樣,再有新的事務連接進來時,它們就只能查詢到已經提交過的事務數據了。但是對於當前事務來說,它們看到的還是未提交的數據,例如:

但是這樣還有問題,那就是假設一個事務在操作數據時,其他事務干擾了這個事務的數據。例如:

雖然 READ COMMITTED 讓我們只能讀取到其他事務已經提交的數據,但還是會出現問題,就是 在讀取同一個表的數據時,可能會發生前後不一致的情況。* 這被稱為* 不可重複讀現象 ( READ COMMITTED ) 。

將隔離級別設置為 REPEATABLE READ ( 可被重複讀取 ) :

測試 REPEATABLE READ ,假設在兩個不同的連接上分別執行 START TRANSACTION :

當前事務開啟後,沒提交之前,查詢不到,提交後可以被查詢到。但是,在提交之前其他事務被開啟了,那麼在這條事務線上,就不會查詢到當前有操作事務的連接。相當於開闢出一條單獨的線程。

無論小張是否執行過 COMMIT ,在小王這邊,都不會查詢到小張的事務記錄,而是只會查詢到自己所處事務的記錄:

這是 因為小王在此之前開啟了一個新的事務 ( START TRANSACTION ) * ,那麼* 在他的這條新事務的線上,跟其他事務是沒有聯繫的 ,也就是說,此時如果其他事務正在操作數據,它是不知道的。

然而事實是,在真實的數據表中,小張已經插入了一條數據。但是小王此時並不知道,也插入了同一條數據,會發生什麼呢?

報錯了,操作被告知已存在主鍵為 6 的字段。這種現象也被稱為 幻讀,一個事務提交的數據,不能被其他事務讀取到 。

顧名思義,就是所有事務的 寫入操作 全都是串行化的。什麼意思?把隔離級別修改成 SERIALIZABLE :

還是拿小張和小王來舉例:

此時會發生什麼呢?由於現在的隔離級別是 SERIALIZABLE ( 串行化 ) ,串行化的意思就是:假設把所有的事務都放在一個串行的隊列中,那麼所有的事務都會按照 固定順序執行 ,執行完一個事務後再繼續執行下一個事務的 寫入操作 ( 這意味着隊列中同時只能執行一個事務的寫入操作 ) 。

根據這個解釋,小王在插入數據時,會出現等待狀態,直到小張執行 COMMIT 結束它所處的事務,或者出現等待超時。

轉載:

mysql 核心內容-上

1、SQL語句執行流程

MySQL大體上可分為Server層和存儲引擎層兩部分。

Server層:

連接器:TCP握手後服務器來驗證登陸用戶身份,A用戶創建連接後,管理員對A用戶權限修改了也不會影響到已經創建的鏈接權限,必須重新登陸。

查詢緩存:查詢後的結果存儲位置,MySQL8.0版本以後已經取消,因為查詢緩存失效太頻繁,得不償失。

分析器:根據語法規則,判斷你輸入的這個SQL語句是否滿足MySQL語法。

優化器:多種執行策略可實現目標,系統自動選擇最優進行執行。

執行器:判斷是否有權限,將最終任務提交到存儲引擎。

存儲引擎層

負責數據的存儲和提取。其架構模式是插件式的,支持InnoDB、MyISAM、Memory等多個存儲引擎。現在最常用的存儲引擎是InnoDB,它從MySQL 5.5.5版本開始成為了默認存儲引擎(經常用的也是這個)。

SQL執行順序

2、BinLog、RedoLog、UndoLog

BinLog

BinLog是記錄所有數據庫表結構變更(例如create、alter table)以及表數據修改(insert、update、delete)的二進制日誌,主從數據庫同步用到的都是BinLog文件。BinLog日誌文件有三種模式。

STATEMENT 模式

內容:binlog 記錄可能引起數據變更的 sql 語句

優勢:該模式下,因為沒有記錄實際的數據,所以日誌量很少 IO 都消耗很低,性能是最優的

劣勢:但有些操作並不是確定的,比如 uuid() 函數會隨機產生唯一標識,當依賴 binlog 回放時,該操作生成的數據與原數據必然是不同的,此時可能造成無法預料的後果。

ROW 模式

內容:在該模式下,binlog 會記錄每次操作的源數據與修改後的目標數據,StreamSets就要求該模式。

優勢:可以絕對精準的還原,從而保證了數據的安全與可靠,並且複製和數據恢復過程可以是並發進行的

劣勢:缺點在於 binlog 體積會非常大,同時,對於修改記錄多、字段長度大的操作來說,記錄時性能消耗會很嚴重。閱讀的時候也需要特殊指令來進行讀取數據。

MIXED 模式

內容:是對上述STATEMENT 跟 ROW 兩種模式的混合使用。

細節:對於絕大部分操作,都是使用 STATEMENT 來進行 binlog 沒有記錄,只有以下操作使用 ROW 來實現:表的存儲引擎為 NDB,使用了uuid() 等不確定函數,使用了 insert delay 語句,使用了臨時表

主從同步流程:

1、主節點必須啟用二進制日誌,記錄任何修改了數據庫數據的事件。

2、從節點開啟一個線程(I/O Thread)把自己扮演成 mysql 的客戶端,通過 mysql 協議,請求主節點的二進制日誌文件中的事件 。

3、主節點啟動一個線程(dump Thread),檢查自己二進制日誌中的事件,跟對方請求的位置對比,如果不帶請求位置參數,則主節點就會從第一個日誌文件中的第一個事件一個一個發送給從節點。

4、從節點接收到主節點發送過來的數據把它放置到中繼日誌(Relay log)文件中。並記錄該次請求到主節點的具體哪一個二進制日誌文件內部的哪一個位置(主節點中的二進制文件會有多個)。

5、從節點啟動另外一個線程(sql Thread ),把 Relay log 中的事件讀取出來,並在本地再執行一次。

mysql默認的複製方式是異步的,並且複製的時候是有並行複製能力的。主庫把日誌發送給從庫後不管了,這樣會產生一個問題就是假設主庫掛了,從庫處理失敗了,這時候從庫升為主庫後,日誌就丟失了。由此產生兩個概念。

全同步複製

主庫寫入binlog後強制同步日誌到從庫,所有的從庫都執行完成後才返回給客戶端,但是很顯然這個方式的話性能會受到嚴重影響。

半同步複製

半同步複製的邏輯是這樣,從庫寫入日誌成功後返回ACK確認給主庫,主庫收到至少一個從庫的確認就認為寫操作完成。

還可以延伸到由於主從配置不一樣、主庫大事務、從庫壓力過大、網絡震蕩等造成主備延遲,如何避免這個問題?主備切換的時候用可靠性優先原則還是可用性優先原則?如何判斷主庫Crash了?互為主備的情況下如何避免主備循環複製?被刪庫跑路了如何正確恢復?( o )… 感覺越來越扯到DBA的活兒上去了。

RedoLog

可以先通過下面demo理解:

飯點記賬可以把賬單寫在賬本上也可以寫在粉板上。有人賒賬或者還賬的話,一般有兩種做法:

1、直接把賬本翻出來,把這次賒的賬加上去或者扣除掉。

2、先在粉板上記下這次的賬,等打烊以後再把賬本翻出來核算。

生意忙時選後者,因為前者太麻煩了。得在密密麻麻的記錄中找到這個人的賒賬總額信息,找到之後再拿出算盤計算,最後再將結果寫回到賬本上。

同樣在MySQL中如果每一次的更新操作都需要寫進磁盤,然後磁盤也要找到對應的那條記錄,然後再更新,整個過程IO成本、查找成本都很高。而粉板和賬本配合的整個過程就是MySQL用到的是Write-Ahead Logging 技術,它的關鍵點就是先寫日誌,再寫磁盤。此時賬本 = BinLog,粉板 = RedoLog。

1、 記錄更新時,InnoDB引擎就會先把記錄寫到RedoLog(粉板)裡面,並更新內存。同時,InnoDB引擎會在空閑時將這個操作記錄更新到磁盤裡面。

2、 如果更新太多RedoLog處理不了的時候,需先將RedoLog部分數據寫到磁盤,然後擦除RedoLog部分數據。RedoLog類似轉盤。

RedoLog有write pos 跟checkpoint

write pos :是當前記錄的位置,一邊寫一邊後移,寫到第3號文件末尾後就回到0號文件開頭。

check point:是當前要擦除的位置,也是往後推移並且循環的,擦除記錄前要把記錄更新到數據文件。

write pos和check point之間的是粉板上還空着的部分,可以用來記錄新的操作。如果write pos追上checkpoint,表示粉板滿了,這時候不能再執行新的更新,得停下來先擦掉一些記錄,把checkpoint推進一下。

有了redo log,InnoDB就可以保證即使數據庫發生異常重啟,之前提交的記錄都不會丟失,這個能力稱為crash-safe。 redolog兩階段提交:為了讓binlog跟redolog兩份日誌之間的邏輯一致。提交流程大致如下:

1 prepare階段 — 2 寫binlog — 3 commit

當在2之前崩潰時,重啟恢復後發現沒有commit,回滾。備份恢復:沒有binlog 。一致

當在3之前崩潰時,重啟恢複發現雖沒有commit,但滿足prepare和binlog完整,所以重啟後會自動commit。備份:有binlog. 一致

binlog跟redolog區別:

redo log是InnoDB引擎特有的;binlog是MySQL的Server層實現的,所有引擎都可以使用。

redo log是物理日誌,記錄的是在某個數據頁上做了什麼修改;binlog是邏輯日誌,記錄的是這個語句的原始邏輯,比如給ID=2這一行的c字段加1。

redo log是循環寫的,空間固定會用完;binlog是可以追加寫入的。追加寫是指binlog文件寫到一定大小後會切換到下一個,並不會覆蓋以前的日誌。

UndoLog

UndoLog 一般是邏輯日誌,主要分為兩種:

insert undo log

代表事務在insert新記錄時產生的undo log, 只在事務回滾時需要,並且在事務提交後可以被立即丟棄

update undo log

事務在進行update或delete時產生的undo log; 不僅在事務回滾時需要,在快照讀時也需要;所以不能隨便刪除,只有在快速讀或事務回滾不涉及該日誌時,對應的日誌才會被purge線程統一清除

3、MySQL中的索引

索引的常見模型有哈希表、有序數組和搜索樹。

哈希表:一種以KV存儲數據的結構,只適合等值查詢,不適合範圍查詢。

有序數組:只適用於靜態存儲引擎,涉及到插入的時候比較麻煩。可以參考Java中的ArrayList。

搜索樹:按照數據結構中的二叉樹來存儲數據,不過此時是N叉樹(B+樹)。廣泛應用在存儲引擎層中。

B+樹比B樹優勢在於:

B+ 樹非葉子節點存儲的只是索引,可以存儲的更多。B+樹比B樹更加矮胖,IO次數更少。

B+ 樹葉子節點前後管理,更加方便範圍查詢。同時結果都在葉子節點,查詢效率穩定。

B+樹中更有利於對數據掃描,可以避免B樹的回溯掃描。

索引的優點:

1、唯一索引可以保證每一行數據的唯一性

2、提高查詢速度

3、加速表與表的連接

4、顯著的減少查詢中分組和排序的時間

5、通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。

索引的缺點:

1、創建跟維護都需要耗時

2、創建索引時,需要對錶加鎖,在鎖表的同時,可能會影響到其他的數據操作

3、 索引需要磁盤的空間進行存儲,磁盤佔用也很快。

4、當對表中的數據進行CRUD的時,也會觸發索引的維護,而維護索引需要時間,可能會降低數據操作性能

索引設計的原則不應該:

1、索引不是越多越好。索引太多,維護索引需要時間跟空間。

2、 頻繁更新的數據,不宜建索引。

3、數據量小的表沒必要建立索引。

應該:

1、重複率小的列建議生成索引。因為重複數據少,索引樹查詢更有效率,等價基數越大越好。

2、數據具有唯一性,建議生成唯一性索引。在數據庫的層面,保證數據正確性

3、頻繁group by、order by的列建議生成索引。可以大幅提高分組和排序效率

4、經常用於查詢條件的字段建議生成索引。通過索引查詢,速度更快

索引失效的場景

1、模糊搜索:左模糊或全模糊都會導致索引失效,比如’%a’和’%a%’。但是右模糊是可以利用索引的,比如’a%’ 。

2、隱式類型轉換:比如select * from t where name = xxx , name是字符串類型,但是沒有加引號,所以是由MySQL隱式轉換的,所以會讓索引失效 3、當語句中帶有or的時候:比如select * from t where name=‘sw’ or age=14

4、不符合聯合索引的最左前綴匹配:(A,B,C)的聯合索引,你只where了C或B或只有B,C

關於索引的知識點:

主鍵索引:主鍵索引的葉子節點存的是整行數據信息。在InnoDB里,主鍵索引也被稱為聚簇索引(clustered index)。主鍵自增是無法保證完全自增的哦,遇到唯一鍵衝突、事務回滾等都可能導致不連續。

唯一索引:以唯一列生成的索引,該列不允許有重複值,但允許有空值(NULL)

普通索引跟唯一索引查詢性能:InnoDB的數據是按數據頁為單位來讀寫的,默認每頁16KB,因此這兩種索引查詢數據性能差別微乎其微。

change buffer:普通索引用在更新過程的加速,更新的字段如果在緩存中,如果是普通索引則直接更新即可。如果是唯一索引需要將所有數據讀入內存來確保不違背唯一性,所以盡量用普通索引。

非主鍵索引:非主鍵索引的葉子節點內容是主鍵的值。在InnoDB里,非主鍵索引也被稱為二級索引(secondary index)

回表:先通過數據庫索引掃描出數據所在的行,再通過行主鍵id取出索引中未提供的數據,即基於非主鍵索引的查詢需要多掃描一棵索引樹。

覆蓋索引:如果一個索引包含(或者說覆蓋)所有需要查詢的字段的值,我們就稱之為覆蓋索引。

聯合索引:相對單列索引,組合索引是用多個列組合構建的索引,一次性最多聯合16個。

最左前綴原則:對多個字段同時建立的組合索引(有順序,ABC,ACB是完全不同的兩種聯合索引) 以聯合索引(a,b,c)為例,建立這樣的索引相當於建立了索引a、ab、abc三個索引。另外組合索引實際還是一個索引,並非真的創建了多個索引,只是產生的效果等價於產生多個索引。

索引下推:MySQL 5.6引入了索引下推優化,可以在索引遍歷過程中,對索引中包含的字段先做判斷,過濾掉不符合條件的記錄,減少回表字數。

索引維護:B+樹為了維護索引有序性涉及到頁分裂跟頁合併。增刪數據時需考慮頁空間利用率。

自增主鍵:一般會建立與業務無關的自增主鍵,不會觸發葉子節點分裂。

延遲關聯:通過使用覆蓋索引查詢返回需要的主鍵,再根據主鍵關聯原表獲得需要的數據。

InnoDB存儲: * .frm文件是一份定義文件,也就是定義數據庫表是一張怎麼樣的表。*.ibd文件則是該表的索引,數據存儲文件,既該表的所有索引樹,所有行記錄數據都存儲在該文件中。

MyISAM存儲:* .frm文件是一份定義文件,也就是定義數據庫表是一張怎麼樣的表。* .MYD文件是MyISAM存儲引擎表的所有行數據的文件。* .MYI文件存放的是MyISAM存儲引擎表的索引相關數據的文件。MyISAM引擎下,表數據和表索引數據是分開存儲的。

MyISAM查詢:在MyISAM下,主鍵索引和輔助鍵索引都屬於非聚簇索引。查詢不管是走主鍵索引,還是非主鍵索引,在葉子結點得到的都是目的數據的地址,還需要通過該地址,才能在數據文件中找到目的數據。

PS:InnoDB支持聚簇索引,MyISAM不支持聚簇索引

4、SQL事務隔離級別

ACID的四個特性

原子性(Atomicity):把多個操作放到一個事務中,保證這些操作要麼都成功,要麼都不成功

一致性(Consistency):理解成一串對數據進行操作的程序執行下來,不會對數據產生不好的影響,比如憑空產生,或消失

隔離性(Isolation,又稱獨立性):隔離性的意思就是多個事務之間互相不干擾,即使是並發事務的情況下,他們只是兩個並發執行沒有交集,互不影響的東西;當然實現中,也不一定需要這麼完整隔離性,即不一定需要這麼的互不干擾,有時候還是允許有部分干擾的。所以MySQL可以支持4種事務隔離性

持久性(Durability):當某個操作操作完畢了,那麼結果就是這樣了,並且這個操作會持久化到日誌記錄中

PS:ACID中C與CAP定理中C的區別

ACID的C着重強調單數據庫事務操作時,要保證數據的完整和正確性,數據不會憑空消失跟增加。CAP 理論中的C指的是對一個數據多個備份的讀寫一致性

事務操作可能會出現的數據問題

1、臟讀(dirty read):B事務更改數據還未提交,A事務已經看到並且用了。B事務如果回滾,則A事務做錯了

2、 不可重複讀(non-repeatable read):不可重複讀的重點是修改: 同樣的條件, 你讀取過的數據, 再次讀取出來發現值不一樣了,只需要鎖住滿足條件的記錄

3、 幻讀(phantom read):事務A先修改了某個表的所有紀錄的狀態字段為已處理,未提交;事務B也在此時新增了一條未處理的記錄,並提交了;事務A隨後查詢記錄,卻發現有一條記錄是未處理的造成幻讀現象,幻讀僅專指新插入的行。幻讀會造成語義上的問題跟數據一致性問題。

4、 在可重複讀RR隔離級別下,普通查詢是快照讀,是不會看到別的事務插入的數據的。因此,幻讀在當前讀下才會出現。要用間隙鎖解決此問題。

在說隔離級別之前,你首先要知道,你隔離得越嚴實,效率就會越低。因此很多時候,我們都要在二者之間尋找一個平衡點。SQL標準的事務隔離級別由低到高如下: 上圖從上到下的模式會導致系統的並行性能依次降低,安全性依次提高。

讀未提交:別人改數據的事務尚未提交,我在我的事務中也能讀到。

讀已提交(Oracle默認):別人改數據的事務已經提交,我在我的事務中才能讀到。

可重複讀(MySQL默認):別人改數據的事務已經提交,我在我的事務中也不去讀,以此保證重複讀一致性。

串行:我的事務尚未提交,別人就別想改數據。

標準跟實現:上面都是關於事務的標準,但是每一種數據庫都有不同的實現,比如MySQL InnDB 默認為RR級別,但是不會出現幻讀。因為當事務A更新了所有記錄的某個字段,此時事務A會獲得對這個表的表鎖,因為事務A還沒有提交,所以事務A獲得的鎖沒有釋放,此時事務B在該表插入新記錄,會因為無法獲得該表的鎖,則導致插入操作被阻塞。只有事務A提交了事務後,釋放了鎖,事務B才能進行接下去的操作。所以可以說 MySQL的RR級別的隔離是已經實現解決了臟讀,不可重複讀和幻讀的。

5、MySQL中的鎖

無論是Java的並發編程還是數據庫的並發操作都會涉及到鎖,研發人員引入了悲觀鎖跟樂觀鎖這樣一種鎖的設計思想。

悲觀鎖:

優點:適合在寫多讀少的並發環境中使用,雖然無法維持非常高的性能,但是在樂觀鎖無法提更好的性能前提下,可以做到數據的安全性

缺點:加鎖會增加系統開銷,雖然能保證數據的安全,但數據處理吞吐量低,不適合在讀書寫少的場合下使用

樂觀鎖:

優點:在讀多寫少的並發場景下,可以避免數據庫加鎖的開銷,提高DAO層的響應性能,很多情況下ORM工具都有帶有樂觀鎖的實現,所以這些方法不一定需要我們人為的去實現。

缺點:在寫多讀少的並發場景下,即在寫操作競爭激烈的情況下,會導致CAS多次重試,衝突頻率過高,導致開銷比悲觀鎖更高。

實現:數據庫層面的樂觀鎖其實跟CAS思想類似, 通數據版本號或者時間戳也可以實現。

數據庫並發場景主要有三種:

讀-讀:不存在任何問題,也不需要並發控制

讀-寫:有隔離性問題,可能遇到臟讀,幻讀,不可重複讀

寫-寫:可能存更新丟失問題,比如第一類更新丟失,第二類更新丟失

兩類更新丟失問題:

第一類更新丟失:事務A的事務回滾覆蓋了事務B已提交的結果 第二類更新丟失:事務A的提交覆蓋了事務B已提交的結果

為了合理貫徹落實鎖的思想,MySQL中引入了雜七雜八的各種鎖:

鎖分類

MySQL支持三種層級的鎖定,分別為

表級鎖定

MySQL中鎖定粒度最大的一種鎖,最常使用的MYISAM與INNODB都支持表級鎖定。

頁級鎖定

是MySQL中鎖定粒度介於行級鎖和表級鎖中間的一種鎖,表級鎖速度快,但衝突多,行級衝突少,但速度慢。所以取了折衷的頁級,一次鎖定相鄰的一組記錄。

行級鎖定

Mysql中鎖定粒度最細的一種鎖,表示只針對當前操作的行進行加鎖。行級鎖能大大減少數據庫操作的衝突。其加鎖粒度最小,但加鎖的開銷也最大行級鎖不一定比表級鎖要好:鎖的粒度越細,代價越高,相比表級鎖在表的頭部直接加鎖,行級鎖還要掃描找到對應的行對其上鎖,這樣的代價其實是比較高的,所以表鎖和行鎖各有所長。

MyISAM中的鎖

雖然MySQL支持表,頁,行三級鎖定,但MyISAM存儲引擎只支持表鎖。所以MyISAM的加鎖相對比較開銷低,但數據操作的並發性能相對就不高。但如果寫操作都是尾插入,那還是可以支持一定程度的讀寫並發

從MyISAM所支持的鎖中也可以看出,MyISAM是一個支持讀讀並發,但不支持通用讀寫並發,寫寫並發的數據庫引擎,所以它更適合用於讀多寫少的應用場合,一般工程中也用的較少。

InnoDB中的鎖

該模式下支持的鎖實在是太多了,具體如下:

共享鎖和排他鎖 (Shared and Exclusive Locks)

意向鎖(Intention Locks)

記錄鎖(Record Locks)

間隙鎖(Gap Locks)

臨鍵鎖 (Next-Key Locks)

插入意向鎖(Insert Intention Locks)

主鍵自增鎖 (AUTO-INC Locks)

空間索引斷言鎖(Predicate Locks for Spatial Indexes)

舉個栗子,比如行鎖里的共享鎖跟排它鎖:lock in share modle 共享讀鎖:

為了確保自己查到的數據沒有被其他的事務正在修改,也就是說確保查到的數據是最新的數據,並且不允許其他人來修改數據。但是自己不一定能夠修改數據,因為有可能其他的事務也對這些數據使用了 in share mode 的方式上了S 鎖。如果不及時的commit 或者rollback 也可能會造成大量的事務等待。

for update排它寫鎖:

為了讓自己查到的數據確保是最新數據,並且查到後的數據只允許自己來修改的時候,需要用到for update。相當於一個 update 語句。在業務繁忙的情況下,如果事務沒有及時的commit或者rollback 可能會造成其他事務長時間的等待,從而影響數據庫的並發使用效率。

Gap Lock間隙鎖:

1、行鎖只能鎖住行,如果在記錄之間的間隙插入數據就無法解決了,因此MySQL引入了間隙鎖(Gap Lock)。間隙鎖是左右開區間。間隙鎖之間不會衝突。

2、間隙鎖和行鎖合稱NextKeyLock,每個NextKeyLock是前開後閉區間。

間隙鎖加鎖原則(學完忘那種):

1、加鎖的基本單位是 NextKeyLock,是前開後閉區間。

2、查找過程中訪問到的對象才會加鎖。

3、索引上的等值查詢,給唯一索引加鎖的時候,NextKeyLock退化為行鎖。

4、索引上的等值查詢,向右遍歷時且最後一個值不滿足等值條件的時候,NextKeyLock退化為間隙鎖。

5、唯一索引上的範圍查詢會訪問到不滿足條件的第一個值為止。

mysql存儲過程知識點難學嗎?

MySQL存儲過程 一、存儲過程 1.1 什麼是存儲過程 存儲過程(Stored Procedure)是在大型數據庫系統中,一組為了完成特定功能的SQL 語句集,它存儲在數據庫中,一次編譯後永久有效,用戶通…,確實有一定的難度!

昭通java培訓學校告訴你零基礎如何mysql學習?

最近,有很多學員留言讓我整理一下“零基礎如何mysql學習?”.今天昭通電腦培訓就整理一下學習MySQL你需要掌握的知識點以及送給新手學習的建議,希望對大家能夠有所幫助!

給新手的學習建議:

1.在學習新的東西的時候,我們至少從三個問題開始。What?why?how?

2.學習需要堅持,如果還沒準備好堅持半年比較枯燥的MySQL之旅,那麼就別開始。

3.學習東西不在多,在精,市面上有非常多的MySQL教程,不要瞎學,今天這裡學一點,明天那裡學一點,這樣你學的都只是知識點,無法形成一個知識面,知識網絡。

4.在學習過程中充滿好奇,使用google進行問題搜索,千萬不要使用度娘了,質量不高。至於怎麼用Google,請自行搜索。

5.學習的目的在於使用,因此,不要僅僅看書,看一遍,看兩遍,你可能還是沒什麼感覺。因此學習一開始,就要動手練習,把資料上的情況,模擬一下。

6.請不要在windows上安裝mysql進行學習,因為工作中都是linux系統。我們需要從一開始就是實戰,就是生產環境。

7.保持好心態,一步一個腳印的前進。

學習MySQL你需要掌握的知識點:

1.系統,當然windos基本的要會。然後就是Linux系統,現在做MySQLDBA的系統多數都是Linux系統,而生產環境大多又是RedHat,Centos。其他的Linux和Unix系統可以只做了解。

2.Linux基礎,網絡,IO,內存,磁盤,CPU。包括不限於安裝,啟動過程,目錄結構,遠程登錄,文件屬性與管理,用戶與用戶權限,LAMP結構vim,yum等shell命令,dns,ftp,以及一些常用工具。

3.MySQL基礎:MySQL安裝、MySQL體系結構,SQL,MySQL管理維護。

4.數據備份與恢復,常用的引擎:MyISAM、Innodb、NDB等。

5.數據庫設計優化,一個好的MySQL系統,往往從設計開始。

6.SQL優化,參數優化,監控,安全等。

7.MySQL負載均衡,讀寫分離,MHA,MMM高可用架構,以及分布式架構:mycat、maxscale、galeracluster、MySQLGroupReplication等。

8.mysql5.6,mysql5.7新特性,mariadb、percona分支的差異和特點。

9.MySQLJSON、MySQLmemcached。

10.常見MySQL搭配的緩存系統,redis,memcached,以及NOSQL、NEWSQL。

以上,就是小編為大家整理的mysql學習你需要掌握的知識點以及送給新手學習的建議,希望能夠幫助到大家!

sql數據庫基礎知識

sql數據庫基礎知識:

一、SQL 概述

1、什麼是 SQL

SQL(Structured Query Language)是“結構化查詢語言”,它是對關係型數據庫的操作語言。它可以應用到所有關係型數據庫中,例如:MySQL、Oracle、SQL Server 等。SQL 標準(ANSI/ISO)有:SQL-92:1992 年發布的 SQL 語言准;SQL:1999:1999 年發布的 SQL 語言標籤;SQL:2003:2003 年發布的 SQL 語言標籤;這些標準就與 JDK 的版本一樣,在新的版本中總要有一些語法的變化。不同時期的數據庫對不同標準做了實現。

雖然 SQL 可以用在所有關係型數據庫中,但很多數據庫還都有標準之後的一些語法,我們可以稱之為“方言”。例如 MySQL 中的 LIMIT 語句就是 MySQL 獨有的方言,其它數據庫都不支持!當然,Oracle 或 SQL Server 都有自己的方言。

MySQL 主從,5 分鐘帶你掌握

MySQL 主從一直是面試常客,裡面的知識點雖然基礎,但是能回答全的同學不多。

比如樓哥之前面試小米,就被問到過主從複製的原理,以及主從延遲的解決方案,因為回答的非常不錯,給面試官留下非常好的印象。你之前面試,有遇到過哪些 MySQL 主從的問題呢?

所謂 MySQL 主從,就是建立兩個完全一樣的數據庫,一個是主庫,一個是從庫, 主庫對外提供讀寫的操作,從庫對外提供讀的操作 ,下面是一主一從模式:

對於數據庫單機部署,在 4 核 8G 的機器上運行 MySQL 5.7 時,大概可以支撐 500 的 TPS 和 10000 的 QPS, 當遇到一些活動時,查詢流量驟然,就需要進行主從分離。

大部分系統的訪問模型是讀多寫少,讀寫請求量的差距可能達到幾個數量級,所以我們可以通過一主多從的方式, 主庫只負責寫入和部分核心邏輯的查詢,多個從庫只負責查詢,提升查詢性能,降低主庫壓力。

MySQL 主從還能做到服務高可用,當主庫宕機時,從庫可以切成主庫,保證服務的高可用,然後主庫也可以做數據的容災備份。

整體場景總結如下:

MySQL 的主從複製是依賴於 binlog 的,也就是記錄 MySQL 上的所有變化並以二進制形式保存在磁盤上二進制日誌文件。

主從複製就是將 binlog 中的數據從主庫傳輸到從庫上,一般這個過程是異步的,即主庫上的操作不會等待 binlog 同步的完成。

詳細流程如下:

當主庫和從庫數據同步時,突然中斷怎麼辦?因為主庫與從庫之間維持了一個長鏈接,主庫內部有一個線程,專門服務於從庫的這個長鏈接的。

對於下面的情況,假如主庫執行如下 SQL,其中 a 和 create_time 都是索引:

我們知道,數據選擇了 a 索引和選擇 create_time 索引,最後 limit 1 出來的數據一般是不一樣的。

所以就會存在這種情況:在 binlog = statement 格式時,主庫在執行這條 SQL 時,使用的是索引 a,而從庫在執行這條 SQL 時,使用了索引 create_time,最後主從數據不一致了。

那麼我們改如何解決呢?

可以把 binlog 格式修改為 row,row 格式的 binlog 日誌記錄的不是 SQL 原文,而是兩個 event:Table_map 和 Delete_rows。

Table_map event 說明要操作的表,Delete_rows event用於定義要刪除的行為,記錄刪除的具體行數。 row 格式的 binlog 記錄的就是要刪除的主鍵 ID 信息,因此不會出現主從不一致的問題。

但是如果 SQL 刪除 10 萬行數據,使用 row 格式就會很占空間的,10 萬條數據都在 binlog 裡面,寫 binlog 的時候也很耗 IO。但是 statement 格式的 binlog 可能會導致數據不一致。

設計 MySQL 的大叔想了一個折中的方案,mixed 格式的 binlog,其實就是 row 和 statement 格式混合使用, 當 MySQL 判斷可能數據不一致時,就用 row 格式,否則使用就用 statement 格式。

有時候我們遇到從數據庫中獲取不到信息的詭異問題時,會糾結於代碼中是否有一些邏輯會把之前寫入的內容刪除,但是你又會發現,過了一段時間再去查詢時又可以讀到數據了,這基本上就是主從延遲在作怪。

主從延遲,其實就是“從庫回放” 完成的時間,與 “主庫寫 binlog” 完成時間的差值, 會導致從庫查詢的數據,和主庫的不一致 。

談到 MySQL 數據庫主從同步延遲原理,得從 MySQL 的主從複製原理說起:

總結一下主從延遲的主要原因 :主從延遲主要是出現在 “relay log 回放” 這一步,當主庫的 TPS 並發較高,產生的 DDL 數量超過從庫一個 SQL 線程所能承受的範圍,那麼延時就產生了,當然還有就是可能與從庫的大型 query 語句產生了鎖等待。

我們一般會把從庫落後的時間作為一個重點的數據庫指標做監控和報警,正常的時間是在毫秒級別,一旦落後的時間達到了秒級別就需要告警了。

解決該問題的方法,除了縮短主從延遲的時間,還有一些其它的方法,基本原理都是盡量不查詢從庫。

具體解決方案如下:

在實際應用場景中,對於一些非常核心的場景,比如庫存,支付訂單等,需要直接查詢從庫,其它非核心場景,就不要去查主庫了。

兩台機器 A 和 B,A 為主庫,負責讀寫,B 為從庫,負責讀數據。

如果 A 庫發生故障,B 庫成為主庫負責讀寫,修復故障後,A 成為從庫,主庫 B 同步數據到從庫 A。

一台主庫多台從庫,A 為主庫,負責讀寫,B、C、D為從庫,負責讀數據。

如果 A 庫發生故障,B 庫成為主庫負責讀寫,C、D負責讀,修復故障後,A 也成為從庫,主庫 B 同步數據到從庫 A。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/278422.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-19 13:22
下一篇 2024-12-19 13:22

相關推薦

  • 如何修改mysql的端口號

    本文將介紹如何修改mysql的端口號,方便開發者根據實際需求配置對應端口號。 一、為什麼需要修改mysql端口號 默認情況下,mysql使用的端口號是3306。在某些情況下,我們需…

    編程 2025-04-29
  • Python wordcloud入門指南

    如何在Python中使用wordcloud庫生成文字雲? 一、安裝和導入wordcloud庫 在使用wordcloud前,需要保證庫已經安裝並導入: !pip install wo…

    編程 2025-04-29
  • Python小波分解入門指南

    本文將介紹Python小波分解的概念、基本原理和實現方法,幫助初學者掌握相關技能。 一、小波變換概述 小波分解是一種廣泛應用於數字信號處理和圖像處理的方法,可以將信號分解成多個具有…

    編程 2025-04-29
  • Python 常用數據庫有哪些?

    在Python編程中,數據庫是不可或缺的一部分。隨着互聯網應用的不斷擴大,處理海量數據已成為一種趨勢。Python有許多成熟的數據庫管理系統,接下來我們將從多個方面介紹Python…

    編程 2025-04-29
  • openeuler安裝數據庫方案

    本文將介紹在openeuler操作系統中安裝數據庫的方案,並提供代碼示例。 一、安裝MariaDB 下面介紹如何在openeuler中安裝MariaDB。 1、更新軟件源 sudo…

    編程 2025-04-29
  • Python豎線圖:從入門到精通

    Python豎線圖,即Python的繪圖工具matplotlib中的一種圖形類型,具有直觀、易於理解的特點,適用於各種數據分析和可視化場景。本文從初學者角度出發,介紹Python豎…

    編程 2025-04-29
  • Python操作MySQL

    本文將從以下幾個方面對Python操作MySQL進行詳細闡述: 一、連接MySQL數據庫 在使用Python操作MySQL之前,我們需要先連接MySQL數據庫。在Python中,我…

    編程 2025-04-29
  • 數據庫第三範式會有刪除插入異常

    如果沒有正確設計數據庫,第三範式可能導致刪除和插入異常。以下是詳細解釋: 一、什麼是第三範式和範式理論? 範式理論是關係數據庫中的一個規範化過程。第三範式是範式理論中的一種常見形式…

    編程 2025-04-29
  • MySQL遞歸函數的用法

    本文將從多個方面對MySQL遞歸函數的用法做詳細的闡述,包括函數的定義、使用方法、示例及注意事項。 一、遞歸函數的定義 遞歸函數是指在函數內部調用自身的函數。MySQL提供了CRE…

    編程 2025-04-29
  • Python爬取數據指南-從入門到精通

    Python爬蟲是指用Python編寫程序,自動化地獲取網絡上的信息,並進行處理、分析和存儲。以下是Python爬取數據的指南,從入門到精通。 一、獲取網頁數據 Python爬蟲的…

    編程 2025-04-29

發表回復

登錄後才能評論