MySQL基礎知識(7)

恒辉信达發表於2024-11-19

資料庫自增主鍵可能遇到什麼問題?

插入效能問題:

在高併發的插入操作中,自增主鍵可能會成為效能瓶頸。因為每次插入新記錄時,都需要獲取一個新的自增ID,這個操作是序列的,無法併發執行。MySQL在生成自增ID時,需要確保ID的唯一性和遞增性,這在高併發場景下可能會導致效能下降。

主鍵耗盡問題:

如果表的記錄非常多,可能會出現自增主鍵耗盡的情況。尤其是對於定義為整型的自增主鍵,如果插入的記錄數超過了整型的最大值(例如,INT型別的最大值為2147483647),就無法再插入新的記錄。這可能導致資料表無法繼續擴充套件,從而影響系統的正常執行。

分散式系統問題:

在分散式系統中,如果多個資料庫節點都需要生成自增主鍵,就需要保證生成的主鍵在全域性是唯一的。然而,MySQL的自增主鍵是在單個資料庫例項內保證唯一的,無法在全域性範圍內保證唯一性。這通常需要引入額外的機制或工具,如分散式ID生成器,來確保全域性唯一性。

自增主鍵的連續性:

MySQL的自增主鍵在某些情況下可能不連續。例如,在刪除某些記錄後,重新插入新記錄時,自增主鍵的值可能會跳過之前刪除的記錄所使用的ID值。此外,在資料庫例項重啟後,自增主鍵的值也可能從之前的最大值繼續遞增,而不是從1開始。這可能導致自增主鍵的值在邏輯上看起來不連續。

安全問題:

使用自增主鍵作為公開資料值可能存在安全風險。例如,在電商系統中,如果商品ID是自增主鍵,使用者可能會透過修改ID值來獲取其他商品的資訊,或者透過ID值推測出資料庫中商品的總數。這可能會洩露系統的敏感資訊,對系統的安全性構成威脅。
針對以上問題,可以考慮以下解決方案:

對於插入效能問題,可以透過最佳化資料庫配置、使用更高效能的儲存引擎、或者考慮使用其他型別的主鍵(如UUID)來緩解。
對於主鍵耗盡問題,可以考慮使用更大範圍的整數型別(如BIGINT)作為主鍵,或者採用其他型別的主鍵(如UUID)來避免主鍵耗盡的問題。
對於分散式系統問題,可以使用分散式ID生成器來生成全域性唯一的ID值,確保在多個資料庫節點之間不會產生主鍵衝突。
對於自增主鍵的連續性問題,需要明確瞭解自增主鍵的工作原理和特性,並在設計系統時考慮到這一點。如果需要連續的自增主鍵值,可以考慮在單個資料庫例項內進行操作,並避免刪除記錄或重啟資料庫例項。

MVCC底層原理

MySQL資料庫的MVCC(Multi-Version Concurrency Control,多版本併發控制)是一種用於提供併發控制的技術,它允許資料庫系統在事務併發執行的情況下保持資料的一致性,同時提高資料庫的併發效能。以下是MySQL資料庫MVCC的底層原理的詳細解釋:

MVCC的核心元件

隱藏欄位:
InnoDB引擎向資料庫中的每一行新增了特定的隱藏欄位,用於記錄事務資訊和回滾指標。
這些隱藏欄位主要包括DB_TRX_ID(事務ID,標識修改當前行資料的最後一個事務)和DB_ROLL_PTR(回滾指標,指向undo log中記錄的上一個版本)。

Undo Log(回滾日誌):
用於記錄資料的歷史版本,支援事務的回滾和多版本併發控制。
每次對資料進行修改時,都會將舊資料寫入undo log,以便在需要時可以恢復到舊版本。

Read View(讀檢視):
每個事務在啟動時都會建立一個Read View,用於判斷哪些資料版本對於當前事務是可見的。
Read View包含了當前系統中活躍的事務ID集合、最小活躍事務ID、下一個要分配的事務ID等資訊。

MVCC的實現原理

版本鏈:
每次對記錄進行改動時,都會記錄一條undo日誌,並透過DB_ROLL_PTR欄位將各個版本的undo日誌連線起來,形成一個版本鏈。
版本鏈的頭節點是當前記錄最新的值,透過回滾指標可以訪問到之前的舊版本。

可見性判斷:
當事務執行SELECT操作時,會根據Read View和版本鏈來判斷每個資料版本的可見性。
如果一個資料版本的事務ID小於所有活躍事務ID或等於當前事務ID,則當前事務可以讀取該版本的資料;否則,需要回滾到更舊的版本進行判斷。

MVCC的讀操作與寫操作

讀操作:
MVCC透過快照讀(一致性非鎖定讀取)實現,讀取的是資料在某個時間點的快照,避免了加鎖操作,提高了併發效能。
在READ COMMITTED隔離級別下,每次快照讀都會生成一個新的Read View;而在REPEATABLE READ隔離級別下,只在事務第一次快照讀時生成Read View,並在整個事務中複用它。

寫操作:
在InnoDB中,寫操作仍然需要加鎖(通常是行級鎖),以保證資料的一致性。
寫操作會更新資料並生成新的undo日誌,同時更新DB_TRX_ID和DB_ROLL_PTR欄位。

事務隔離級別與MVCC

MVCC主要在READ COMMITTED(讀已提交)和REPEATABLE READ(可重複讀)兩個隔離級別下工作。

在READ COMMITTED隔離級別下,每次快照讀都會生成一個新的Read View,因此每次讀取的資料都是最新提交的版本。
在REPEATABLE READ隔離級別下,只在事務第一次快照讀時生成Read View,並在整個事務中複用它,因此在一個事務內多次讀取同一資料的結果是一致的。

MVCC的優勢與不足

優勢:
提高了資料庫的併發效能,透過快照讀避免了讀寫衝突。
減少了鎖的使用,降低了死鎖的機率。
實現了事務的隔離性,保證了資料的一致性。

不足:
增加了儲存空間的消耗,因為需要儲存資料的歷史版本。
提高了資料維護的成本,包括undo log的管理和版本鏈的維護。

資料庫中介軟體瞭解過嗎,sharding jdbc,mycat?

MySQL資料庫中介軟體是一種位於應用程式和MySQL資料庫之間的軟體層,用於提供高可用性、負載均衡、資料分片、快取、讀寫分離等功能。以下是關於MySQL資料庫中介軟體的一些詳細解釋:

主要功能和優勢

負載均衡:
中介軟體可以分攤來自多個客戶端的請求,將它們路由到不同的資料庫例項上,從而避免單點故障並提高系統的整體效能。

故障轉移:
當某個資料庫例項出現故障時,中介軟體可以自動將請求轉發到其他健康的例項上,保證系統的正常執行。

資料分片:
透過中介軟體可以實現資料的水平分片,將資料分佈到不同的節點上,從而提高資料庫的擴充套件性和併發效能。

讀寫分離:
中介軟體可以根據實際情況將讀請求和寫請求分發到不同的節點上,從而提高資料庫的讀寫效能。

自動化管理:
中介軟體可以自動進行資料庫的擴容、縮容和配置調整,簡化了資料庫管理的複雜性。

常見的MySQL資料庫中介軟體

MaxScale:

MariaDB官方提供的中介軟體,支援負載均衡、讀寫分離、故障轉移等功能。
可以透過配置檔案進行靈活的配置,並且具有高效能和可擴充套件性。

ProxySQL:

一個高效能的MySQL代理,支援負載均衡、讀寫分離、故障轉移等功能。
可以透過SQL語句進行配置,並且具有強大的查詢快取和連線池功能。

MyCAT:

一個開源的分散式資料庫中介軟體,支援資料分片、讀寫分離、負載均衡等功能。
可以將多個MySQL資料庫組合成一個邏輯資料庫,並提供統一的訪問介面。

Vitess:

一個由YouTube開發的開源分散式資料庫中介軟體,專為大規模Web服務設計。
支援水平擴充套件、負載均衡、資料分片等功能,並且與MySQL相容。

TiDB:

一個分散式資料庫中介軟體,支援水平擴充套件、負載均衡、事務處理等功能。
使用了分散式一致性演算法,並且具有高可用性和強一致性。

中介軟體的選擇與應用

在選擇MySQL資料庫中介軟體時,需要考慮以下因素:
業務需求:根據業務需求和資料庫架構來選擇適合的中介軟體。
效能要求:考慮中介軟體的效能指標,如吞吐量、響應時間等。
可擴充套件性:考慮中介軟體的可擴充套件性,是否支援水平擴充套件和垂直擴充套件。
相容性:確保中介軟體與現有的MySQL資料庫和應用程式相容。

在應用中介軟體時,需要注意以下幾點:
配置最佳化:根據實際需求對中介軟體進行配置最佳化,以提高效能。
監控與調優:定期監控中介軟體的效能和執行狀態,並進行必要的調優。
安全性:確保中介軟體的安全性,包括使用者認證、授權、審計等功能。

什麼是資料庫連線池?為什麼需要資料庫連線池呢?

MySQL資料庫連線池介紹

工作原理:
連線建立:在應用程式啟動時,連線池會根據配置資訊建立一定數量的資料庫連線,並將它們儲存在池中。
連線使用:當應用程式需要訪問資料庫時,它會向連線池請求一個連線。如果池中有空閒的連線,則立即返回給應用程式使用;如果沒有空閒連線,則根據配置決定是等待空閒連線釋放,還是建立新的連線(如果允許)。
連線釋放:當應用程式完成資料庫操作後,它會將連線釋放回連線池,以便其他請求可以複用。
連線池維護:連線池會定期檢測並關閉無效或空閒時間過長的連線,以保持池中連線的有效性。

主要特性:
資源複用:透過複用現有的連線,避免了頻繁建立和銷燬連線的開銷,提高了系統效能。
提高響應速度:由於不需要每次都建立新的連線,因此可以更快地響應資料庫請求。
限制資源使用:連線池可以限制同時使用的連線數,防止因過多的連線請求而導致資料庫伺服器資源耗盡。
管理簡單:連線池提供了統一的連線管理介面,簡化了資料庫連線的管理和使用。

為什麼需要MySQL資料庫連線池

提高效能:
每次建立或銷燬資料庫連線都會消耗相當多的資源和時間。當系統需要頻繁訪問資料庫時,頻繁的連線和斷開操作會嚴重影響系統效能。
連線池透過複用現有連線,減少了這些開銷,從而顯著提高了系統的響應速度和處理能力。

管理資料庫連線:
在高併發環境中,管理資料庫連線是一個複雜而重要的問題。
MySQL資料庫連線池能夠有效地管理這些連線,透過限制最大連線數來避免資源耗盡和系統崩潰。

節約資源:
資料庫連線是寶貴的資源,特別是在高併發環境中,頻繁的連線和斷開操作會消耗大量的系統資源。
連線池透過複用現有連線,減少了這些資源的浪費。節約資源不僅體現在減少CPU和記憶體的消耗,還體現在減少網路頻寬的使用。

提升系統穩定性:
控制併發連線數可以有效防止資料庫過載,從而避免系統崩潰。
連線池透過健康檢查和連線重試機制,確保連線的可用性和穩定性。

簡化程式設計:
開發人員無需手動管理資料庫連線的建立和銷燬,連線池自動化管理這些操作,使得程式碼更加簡潔和易於維護。
透過使用連線池,開發人員可以專注於業務邏輯的實現,而無需擔心底層的連線管理問題。

資料庫儲存日期格式時,如何考慮時區轉換問題?

時區設定與時區轉換基礎

時區設定:
MySQL資料庫的時區設定可以透過修改配置檔案或使用SET語句來實現。
時區設定的預設值是伺服器的系統時區。

時區轉換原則:
MySQL資料庫中的時區轉換基於儲存和計算的時間戳以UTC(協調世界時)為基準的原則。
資料在儲存和顯示時會根據時區進行轉換。

如何進行時區轉換

使用CONVERT_TZ函式:
CONVERT_TZ函式是MySQL中用於時區轉換的主要函式,它接受三個引數:要轉換的時間戳、原始時區、目標時區。
示例程式碼:SELECT CONVERT_TZ('2022-01-01 12:00:00','UTC','Asia/Shanghai') AS converted_time;

其他時區轉換函式:
除了CONVERT_TZ函式外,MySQL還提供了FROM_UTC_TIMESTAMP和TO_UTC_TIMESTAMP等函式用於時區轉換。

示例程式碼:SELECT FROM_UTC_TIMESTAMP('2022-01-01 12:00:00','+00:00') AS converted_time;

考慮時區轉換的實際情況

插入資料時的時區轉換:
當將日期和時間資料插入到MySQL資料庫時,如果資料是以特定時區提供的,需要將其轉換為UTC或資料庫的時區設定,以確保資料的一致性。

查詢資料時的時區轉換:
當從MySQL資料庫查詢日期和時間資料時,可以根據需要將資料從儲存的時區轉換為所需的時區。
這通常在應用程式級別進行處理,但也可以在資料庫查詢中使用CONVERT_TZ函式進行轉換。

會話時區變化:
MySQL資料庫中的會話時區可以透過設定會話變數來進行調整。
當會話時區發生變化時,已儲存的日期和時間值在查詢時會根據新的會話時區進行轉換。

儲存時區變化:
如果需要更改資料庫中已儲存資料的時區,可以更新資料以反映新的時區設定,並在查詢時進行相應的轉換。

注意事項

時區命名:
不同的系統和資料庫可能使用不同的時區命名方式,需要注意進行轉換。

資料儲存格式:
在插入和查詢資料時,需要確保使用正確的日期和時間格式。

時區轉換函式的引數:
在使用時區轉換函式時,需要確保引數的正確性,避免產生錯誤的結果。

Blob和text有什麼區別?

Blob用於儲存二進位制資料,而Text用於儲存大字串。
Blob值被視為二進位制字串(位元組字串),它們沒有字符集,並且排序和比較基於列值中的位元組的數值。
text值被視為非二進位制字串(字元字串)。它們有一個字符集,並根據字符集的排序規則對值進行排序和比較。

mysql 的內連線、左連線、右連線有什麼區別?

Inner join 內連線,在兩張表進行連線查詢時,只保留兩張表中完全匹配的結果集。
left join 左連線,在兩張表進行連線查詢時,會返回左表所有的行,即使在右表中沒有匹配的記錄。
right join 右連線,在兩張表進行連線查詢時,會返回右表所有的行,即使在左表中沒有匹配的記錄。

說一下資料庫的三大正規化

第一正規化:資料表中的每一列(每個欄位)都不可以再拆分。
第二正規化:在第一正規化的基礎上,分主鍵列完全依賴於主鍵,而不能是依賴於主鍵的一部分。
第三正規化:在滿足第二正規化的基礎上,表中的非主鍵只依賴於主鍵,而不依賴於其他非主鍵。

百萬級別或以上的資料,你是如何刪除的?

選擇合適的刪除方法

TRUNCATE TABLE:
如果需要刪除表中的所有資料,並且不關心刪除操作的日誌記錄或觸發器啟用,那麼TRUNCATE TABLE是一個快速且高效的選擇。
TRUNCATE TABLE會直接刪除表中的所有資料,並且不會逐行刪除,因此速度比DELETE快得多。
需要注意的是,TRUNCATE TABLE無法回滾,並且會重置表的自增列。

DELETE 語句:
如果需要根據特定條件刪除資料,那麼DELETE語句是必需的。
為了提高刪除效率,可以在DELETE語句的WHERE條件中使用索引。
還可以考慮分批刪除資料,以減少對系統資源的佔用和避免長時間的鎖表。

最佳化刪除操作

使用索引:
在刪除操作的WHERE條件中使用索引可以顯著提高刪除速度。
確保在需要刪除的列上建立了合適的索引。

分批刪除:
將需要刪除的資料分成多個批次,每次刪除一部分資料。
可以透過在DELETE語句中使用LIMIT子句來實現分批刪除。
分批刪除可以有效減輕資料庫的壓力,避免長時間的阻塞。

禁用外來鍵約束:
在執行大量刪除操作之前,可以考慮暫時禁用外來鍵約束。
禁用外來鍵約束可以避免在刪除資料時觸發外來鍵約束檢查,從而提高刪除效率。
刪除操作完成後,記得重新啟用外來鍵約束。

使用臨時表:
如果需要保留部分資料而刪除其他資料,可以考慮使用臨時表。
將需要保留的資料插入到臨時表中,然後清空原表,最後將臨時表中的資料重新插入到原表中。
這種方法可以減少對原表的直接操作,提高刪除效率。

事務處理與回滾

如果刪除操作可能涉及大量資料並且需要確保資料的一致性,可以考慮使用事務處理。
在事務中執行刪除操作,並在確認刪除無誤後提交事務。
如果在刪除過程中發生錯誤或需要取消刪除操作,可以回滾事務以恢復資料。

備份與恢復

在執行任何刪除操作之前,務必先備份資料庫或相關表的資料。
備份資料可以使用MySQL的mysqldump工具或其他備份工具。
如果在刪除過程中出現問題或誤刪除了資料,可以透過備份檔案恢復數注意事項。
在執行大量刪除操作時,需要監控資料庫的效能和資源使用情況。
如果刪除操作導致資料庫效能下降或資源緊張,可以考慮在業務低峰期執行刪除操作。
在執行刪除操作之前,務必確保已經瞭解了刪除操作的影響和後果,並獲得了相關人員的授權和批准。

覆蓋索引、回表等這些,瞭解過嗎?

覆蓋索引: 查詢列要被所建的索引覆蓋,不必從資料表中讀取,換句話說查詢列要被所使用的索引覆蓋。
回表:二級索引無法直接查詢所有列的資料,所以透過二級索引查詢到聚簇索引後,再查詢到想要的資料,這種透過二級索引查詢出來的過程,就叫做回表。

相關文章