Amazon Aurora MySQL 的最佳實務 - Amazon Aurora

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

Amazon Aurora MySQL 的最佳實務

此主題包含有關使用資料或將資料遷移至 Amazon Aurora MySQL 資料庫叢集的最佳實務和選項的資訊。本主題中的資訊摘要說明並重申您可以在 管理 Amazon Aurora 資料庫叢集 中找到的部分指導方針和程序。

判斷您連接的資料庫執行個體

若要判斷連線所連接的是 Aurora MySQL 資料庫叢集中的哪個資料庫執行個體,請檢查 innodb_read_only 全域變數,如以下範例所示。

SHOW GLOBAL VARIABLES LIKE 'innodb_read_only';

如果您連線到讀取器資料庫執行個體,則 innodb_read_only 變數設定為 ON。如果您連線至寫入器資料庫執行個體 (例如已佈建叢集中的主要執行個體),則此設定為 OFF

如果要將邏輯新增至您的應用程式碼,以平衡工作負載或確保寫入操作使用的是正確的連接,則此方法很實用。

Aurora MySQL 效能和擴展的最佳實務

您可以應用以下最佳實務,改善 Aurora MySQL 叢集的效能和可擴展性。

使用 T 執行個體類別進行開發和測試

對於不支援需時較長的高工作負載應用程式,使用 db.t2db.t3db.t4g 資料庫執行個體類別的 Amazon Aurora MySQL 執行個體是完美之選。T 執行個體旨在提供適度的基準效能和容量,可視您的工作負載需要大幅提升效能。它們適用非經常或持續使用整個 CPU,但偶爾需要高載的工作負載。建議您在開發、測試伺服器或其他非生產伺服器時,僅使用 T 資料庫執行個體類別。如需 T 執行個體類別的詳細資訊,請參閱爆量效能執行個體

如果您的 Aurora 叢集大於 40 TB,請勿使用 T 執行個體類別。當您的資料庫有大量資料時,管理結構描述物件的記憶體額外負荷可能會超過 T 執行個體的容量。

請不要在 Amazon Aurora MySQL T 執行個體上啟用 MySQL Performance Schema (MySQL 效能結構描述)。如果已啟用 Performance Schema (效能結構描述),執行個體可能會用盡記憶體。

提示

若您的資料庫有時處於閒置狀態,但有時工作負載相當大,則可使用 Aurora Serverless v2 作為 T 執行個體的替代方案。利用 Aurora Serverless v2,您可定義容量範圍,Aurora 會根據目前的工作負載自動擴展或縮小資料庫。如需用量詳細資料,請參閱 使用 Aurora Serverless v2。若需可與 Aurora Serverless v2 搭配使用的資料庫引擎版本,請參閱 要求和限制 Aurora Serverless v2

當您在 Aurora MySQL 資料庫叢集中,使用 T 執行個體作為資料庫執行個體時,我們建議下列作法:

  • 在您的資料庫叢集中,所有執行個體請皆使用相同的資料庫執行個體類別。例如:如果您的寫入器執行個體使用 db.t2.medium,則我們也建議讀取器執行個體使用 db.t2.medium

  • 請不要調整任何與記憶體相關的組態設定,例如 innodb_buffer_pool_size。Aurora 可針對 T 執行個體上的記憶體緩衝區使用一組高度調整的預設值。Aurora 需要這些特殊的預設值,才能在記憶體受限的執行個體上執行。如果您在 T 實例上更改任何與內存相關的設置,則即使您的更改旨在增加緩衝區大小,也更有可能遇到 out-of-memory 條件。

  • 監控您的 CPU 點數餘額 (CPUCreditBalance) 以確保它處於可永續使用的層級。也就是說,CPU 點數的累積速率與使用時速率相同。

    某個執行個體用盡 CPU 點數時,您會看到可用 CPU 立即下降,以及看到執行個體的讀寫延遲增加。此情況會造成執行個體整體效能嚴重降低。

    如果您的 CPU 點數餘額未處於可永續使用的層級,建議您修改資料庫執行個體,以使用其中一個支援的 R 資料庫執行個體類別 (擴展運算)。

    如需監控指標的詳細資訊,請參閱在 Amazon RDS 主控台中檢視指標

  • 監控寫入器執行個體與讀取器執行個體之間的複本延遲 (AuroraReplicaLag)。

    如果讀取器執行個體先於寫入器執行個體耗盡 CPU 點數,則產生的延遲可能會導致讀取器執行個體頻繁重新啟動。當應用程式分散在讀取器執行個體之間的讀取操作負載繁重,而同時寫入器執行個體有少量寫入操作時,此結果很常見。

    如果您看到複本延遲持續增加,請確定資料庫叢集中讀取器執行個體的 CPU 點數餘額尚未用盡。

    如果您的 CPU 點數餘額未處於可永續使用的層級,建議您修改資料庫執行個體,以使用其中一個支援的 R 資料庫執行個體類別 (擴展運算)。

  • 針對已啟用二進位日誌的資料庫叢集,將每個交易的插入數保持在 100 萬個以下。

    如果資料庫叢集的資料庫叢集參數群組的binlog_format參數設定為以外的值OFF,則如果資料庫叢集接收到要插入超過 100 萬個資料列的交易,您的資料庫叢集可能會遇到 out-of-memory條件。您可以監控可釋放記憶體 (FreeableMemory) 指標,以判斷資料庫叢集是否用盡可用的記憶體。然後可以檢查寫入操作 (VolumeWriteIOPS) 指標,以查看寫入器執行個體接收的寫入器操作負載是否繁重。若是這種情況,建議更新您的應用程式,將一個交易中的插入數限制在 100 萬個以下。或者,您可以修改執行個體,以使用其中一個支援的 R 資料庫執行個體類別 (擴展運算)。

使用非同步索引鍵預先提取,將 Amazon Aurora MySQL 索引聯結查詢最佳化

Aurora MySQL 可以使用非同步索引鍵預先提取 (AKP) 功能來改善聯結索引間資料表之查詢的效能。在 JOIN 查詢要求使用批次索引鍵存取 (BKA) 聯結演算法和多範圍讀取 (MRR) 最佳化功能的情況下,透過預期執行查詢所需的資料列,此功能可藉此改善效能。如需 BKA 和 MRR 的詳細資訊,請參閱 MySQL 文件中的封鎖巢狀迴圈和批次索引鍵存取聯結多範圍讀取最佳化

若要利用 AKP 功能,查詢必須同時使用 BKA 和 MRR。一般來說,當查詢的 JOIN 子句使用次要索引,但也需要來自主要索引的一些資料欄時,會發生這類查詢。例如,當 JOIN 子句代表小型外部資料表與大型內部資料表間索引值的對等聯結,並且較大資料表上的索引具有高度選擇性時,您可以使用 AKP。AKP 可與 BKA 和 MRR 共同合作,以在 JOIN 子句的評估期間執行次要至主要索引查詢。AKP 會識別在 JOIN 子句的評估期間執行查詢所需的資料列。然後使用背景執行緒,在執行查詢之前,將包含那些資料列的頁面非同步載入至記憶體。

AKP 適用於 Aurora MySQL 第 2.10 版以上及第 3 版。如需 Aurora MySQL 版本的詳細資訊,請參閱 Amazon Aurora MySQL 的資料庫引擎更新

啟用非同步索引鍵預先提取

您可以透過將 MySQL 伺服器變數 aurora_use_key_prefetch 設定為 on 來啟用 AKP 功能。依預設,此值是設為 on。不過,在您也啟用 BKA 聯結演算法並停用成本型 MRR 功能之前,無法啟用 AKP。若要這麼做,您必須設定 MySQL 伺服器變數 optimizer_switch 的下列值:

  • batched_key_access 設定為 on。此值可控制 BKA 聯結演算法的使用。依預設,此值是設為 off

  • mrr_cost_based 設定為 off。此值可控制成本型 MRR 功能的使用。依預設,此值是設為 on

目前,您只能在工作階段層級設定這些值。下列範例說明如何透過執行 SET 陳述式來設定這些值,來為目前的工作階段啟用 AKP。

mysql> set @@session.aurora_use_key_prefetch=on; mysql> set @@session.optimizer_switch='batched_key_access=on,mrr_cost_based=off';

相同地,您可以使用 SET 陳述式來停用 AKP 和 BKA 聯結演算法,以及為目前的工作階段重新啟用成本型 MRR 功能,如以下範例所示。

mysql> set @@session.aurora_use_key_prefetch=off; mysql> set @@session.optimizer_switch='batched_key_access=off,mrr_cost_based=on';

如需 batched_key_accessmrr_cost_based 最佳化器切換參數的詳細資訊,請參閱 MySQL 文件中的可切換的最佳化

非同步索引鍵預先提取的最佳化查詢

您可以確認查詢是否可利用 AKP 功能。若要這麼做,請使用 EXPLAIN 陳述式在執行查詢之前描繪查詢。EXPLAIN 陳述式提供要針對指定查詢使用之執行計劃的相關資訊。

EXPLAIN 陳述式的輸出中,Extra 資料欄說明執行計劃隨附的其他資訊。如果 AKP 功能適用於查詢中使用的資料表,此資料欄會包括以下其中一個值:

  • Using Key Prefetching

  • Using join buffer (Batched Key Access with Key Prefetching)

下列範例示範使用 EXPLAIN 來檢視可利用 AKP 之查詢的執行計劃。

mysql> explain select sql_no_cache -> ps_partkey, -> sum(ps_supplycost * ps_availqty) as value -> from -> partsupp, -> supplier, -> nation -> where -> ps_suppkey = s_suppkey -> and s_nationkey = n_nationkey -> and n_name = 'ETHIOPIA' -> group by -> ps_partkey having -> sum(ps_supplycost * ps_availqty) > ( -> select -> sum(ps_supplycost * ps_availqty) * 0.0000003333 -> from -> partsupp, -> supplier, -> nation -> where -> ps_suppkey = s_suppkey -> and s_nationkey = n_nationkey -> and n_name = 'ETHIOPIA' -> ) -> order by -> value desc; +----+-------------+----------+------+-----------------------+---------------+---------+----------------------------------+------+----------+-------------------------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+----------+------+-----------------------+---------------+---------+----------------------------------+------+----------+-------------------------------------------------------------+ | 1 | PRIMARY | nation | ALL | PRIMARY | NULL | NULL | NULL | 25 | 100.00 | Using where; Using temporary; Using filesort | | 1 | PRIMARY | supplier | ref | PRIMARY,i_s_nationkey | i_s_nationkey | 5 | dbt3_scale_10.nation.n_nationkey | 2057 | 100.00 | Using index | | 1 | PRIMARY | partsupp | ref | i_ps_suppkey | i_ps_suppkey | 4 | dbt3_scale_10.supplier.s_suppkey | 42 | 100.00 | Using join buffer (Batched Key Access with Key Prefetching) | | 2 | SUBQUERY | nation | ALL | PRIMARY | NULL | NULL | NULL | 25 | 100.00 | Using where | | 2 | SUBQUERY | supplier | ref | PRIMARY,i_s_nationkey | i_s_nationkey | 5 | dbt3_scale_10.nation.n_nationkey | 2057 | 100.00 | Using index | | 2 | SUBQUERY | partsupp | ref | i_ps_suppkey | i_ps_suppkey | 4 | dbt3_scale_10.supplier.s_suppkey | 42 | 100.00 | Using join buffer (Batched Key Access with Key Prefetching) | +----+-------------+----------+------+-----------------------+---------------+---------+----------------------------------+------+----------+-------------------------------------------------------------+ 6 rows in set, 1 warning (0.00 sec)

如需 EXPLAIN 輸出格式的詳細資訊,請參閱 MySQL 文件中的延伸 EXPLAIN 輸出格式

使用雜湊聯結,將大型 Aurora MySQL 聯結查詢最佳化

需要使用對等聯結來聯結大量資料時,雜湊聯結可以改善查詢效能。您可以為 Aurora MySQL 啟用雜湊聯結。

雜湊聯結資料欄可以是任何複雜的表達式。在雜湊聯結資料欄中,您可以利用下列方式來比較各個資料類型:

  • 您可以比較各類別的精確數值資料類型項目,例如 intbigintnumericbit

  • 您可以比較各類別的近似數值資料類型項目,例如 floatdouble

  • 您可以比較各字串類型的項目,以得知字串類型是否有相同的字元集和定序。

  • 您可以比較項目的日期和時間戳記資料類型,以得知類型是否相同。

注意

您無法在不同類別中比較資料類型。

下列限制適用 Aurora MySQL 的雜湊聯結:

  • Aurora MySQL 第 2 版不支援左右外部連接,但第 3 版支援。

  • 不支援半聯結 (例如子查詢),除非先將子查詢具體化。

  • 不支援多資料表更新或刪除。

    注意

    支援單一資料表更新或刪除。

  • BLOB 和空間資料類型資料欄不可為雜湊聯結中的聯結資料欄。

啟用雜湊聯結

若要啟用雜湊聯結:

  • Aurora MySQL 第 2 版 — 將資料庫參數或資料庫叢集參數 aurora_disable_hash_join 設為 0。若關閉 aurora_disable_hash_joinoptimizer_switch 的值將為 hash_join=on

  • Aurora MySQL 第 3 版 — 將 MySQL 伺服器參數 optimizer_switch 設為 block_nested_loop=on

雜湊聯結在 Aurora MySQL 第 3 版中會預設開啟,在 Aurora MySQL 第 2 版則預設關閉。下列範例說明如何為 Aurora MySQL 第 3 版啟用雜湊聯結。您可以發出陳述式 select @@optimizer_switch,以查看哪些其他設定存在於 SET 參數字串中。更新 optimizer_switch 參數中的某個設定不會清除或修改其他設定。

mysql> SET optimizer_switch='block_nested_loop=on';
注意

對於 Aurora MySQL 第 3 版,雜湊聯結支援適用於所有次要版本,預設為開啟。

對於 Aurora MySQL 第 2 版,雜湊聯結支援適用於所有次要版本。在 Aurora MySQL 第 2 版中,雜湊聯結功能一律由 aurora_disable_hash_join 值控制。

利用此設定,最佳化器會根據成本、查詢特質和資源可用性選擇使用雜湊聯結。如果成本估算不正確,您可以強制最佳化器選擇某個雜湊聯結。您可以透過將 MySQL 伺服器變數 hash_join_cost_based 設定為 off 來執行此動作。下列範例說明如何強制最佳化器選擇雜湊聯結。

mysql> SET optimizer_switch='hash_join_cost_based=off';
注意

此設定會覆寫成本類型最佳化工具的決策。雖然該設定對於測試和開發非常有用,但建議您不要在生產環境中使用它。

最佳化雜湊聯結的查詢

若要了解查詢是否可利用雜湊聯結,請先使用 EXPLAIN 陳述式來描繪查詢。EXPLAIN 陳述式提供要針對指定查詢使用之執行計劃的相關資訊。

EXPLAIN 陳述式的輸出中,Extra 資料欄說明執行計劃隨附的其他資訊。如果雜湊聯結適用於查詢中所用的資料表,此資料欄會包括類似以下的值:

  • Using where; Using join buffer (Hash Join Outer table table1_name)

  • Using where; Using join buffer (Hash Join Inner table table2_name)

下列範例示範使用 EXPLAIN 來檢視雜湊聯結查詢的執行計劃。

mysql> explain SELECT sql_no_cache * FROM hj_small, hj_big, hj_big2 -> WHERE hj_small.col1 = hj_big.col1 and hj_big.col1=hj_big2.col1 ORDER BY 1; +----+-------------+----------+------+---------------+------+---------+------+------+----------------------------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+----------+------+---------------+------+---------+------+------+----------------------------------------------------------------+ | 1 | SIMPLE | hj_small | ALL | NULL | NULL | NULL | NULL | 6 | Using temporary; Using filesort | | 1 | SIMPLE | hj_big | ALL | NULL | NULL | NULL | NULL | 10 | Using where; Using join buffer (Hash Join Outer table hj_big) | | 1 | SIMPLE | hj_big2 | ALL | NULL | NULL | NULL | NULL | 15 | Using where; Using join buffer (Hash Join Inner table hj_big2) | +----+-------------+----------+------+---------------+------+---------+------+------+----------------------------------------------------------------+ 3 rows in set (0.04 sec)

在輸出中,Hash Join Inner table 是用來建置雜湊資料表的資料表,而 Hash Join Outer table 是用來探測雜湊資料表的資料表。

如需延伸 EXPLAIN 輸出格式的詳細資訊,請參閱 MySQL 產品文件中的延伸 EXPLAIN 輸出格式

在 Aurora MySQL 2.08 及更高版本中,您可以使用 SQL 提示來影響查詢是否使用雜湊聯結,以及要使用哪些資料表來建置和聯結探測端。如需詳細資訊,請參閱 Aurora MySQL 提示

使用 Amazon Aurora 為 MySQL 資料庫擴展讀取

您可以使用 Amazon Aurora 搭配 MySQL 資料庫執行個體來利用 Amazon Aurora 的讀取擴展功能,並為 MySQL 資料庫執行個體擴展讀取工作負載。若要使用 Aurora 來讀取擴展 MySQL 資料庫執行個體,請建立 Aurora MySQL 資料庫叢集,並讓它成為您 MySQL DB 執行個體的讀取複本。然後連線至 Aurora MySQL 叢集以處理讀取查詢。該來源資料庫可以是 RDS for MySQL 資料庫執行個體,也可以是在 Amazon RDS 外部執行的 MySQL 資料庫。如需詳細資訊,請參閱 使用 Amazon Aurora 為 MySQL 資料庫擴展讀取

最佳化時間戳記操作

當系統變數 time_zone 的值設為 SYSTEM 時,每個需要時區計算的 MySQL 函數呼叫都會進行系統程式庫呼叫。當您執行以高並行方式傳回或變更這類 TIMESTAMP 值的 SQL 陳述式時,可能會遇到延遲、鎖定爭用和 CPU 使用率增加的情況。如需詳細資訊,請參閱 MySQL 文件中的 time_zone

若要避免此行為,建議您將 time_zone 資料庫叢集參數的值變更為 UTC。如需詳細資訊,請參閱 修改資料庫叢集參數群組中的參數

儘管 time_zone 參數是動態的 (不需要重新啟動資料庫伺服器),但新值僅用於新連線。若要確保所有連線都更新為使用新的 time_zone 值,建議您在更新資料庫叢集參數之後回收應用程式連線。

Aurora MySQL 高可用性的最佳實務

您可以應用以下最佳實務,改善 Aurora MySQL 叢集的可用性。

使用 Amazon Aurora 搭配 MySQL 資料庫進行災難復原

您可以使用 Amazon Aurora 搭配 MySQL 資料庫執行個體來建立用於災難復原的離站備份。若要使用 Aurora 進行 MySQL 資料庫執行個體的災難復原,請建立 Amazon Aurora 資料庫叢集,並讓它成為 MySQL 資料庫執行個體的讀取複本。這可套用至 RDS for MySQL 資料庫執行個體,或在 Amazon RDS 外部執行的 MySQL 資料庫。

重要

設定 MySQL 資料庫執行個體與 Amazon Aurora MySQL 資料庫叢集之間的複寫時,您應該監控此複寫以確保其維持正常運作,並在必要時加以修復。

如需如何建立 Amazon Aurora MySQL 資料庫叢集,並讓它成為 MySQL 資料庫執行個體讀取複本的指示,請遵循使用 Amazon Aurora 為 MySQL 資料庫擴展讀取中的程序。

如需災難復原模型的詳細資訊,請參閱 How to choose the best disaster recovery option for your Amazon Aurora MySQL cluster (如何為您的 Amazon Aurora MySQL 叢集選擇最佳災難復原選項)。

從 MySQL 遷移至 Amazon Aurora MySQL 時減少停機時間

從支援線上應用程式的 MySQL 資料庫將資料匯入至 Amazon Aurora MySQL 資料庫叢集時,您可能希望能減少遷移時服務中斷的時間。為此,您可以使用《Amazon Relational Database Service 使用者指南》中減少將資料匯入 MySQL 或 MariaDB 資料庫執行個體時的停機時間所記載的程序。如果您使用的是超大型資料庫,這個程序特別有用。您可以使用此程序來透過降低經過網路傳輸至 AWS的資料量,藉此減少匯入的成本。

此程序列出將資料庫資料的複本傳輸至 Amazon EC2 執行個體,並將資料匯入新的 RDS for MySQL 資料庫執行個體的步驟。因為 Amazon Aurora 與 MySQL 相容,您可以改為對目標 Amazon RDS MySQL 資料庫執行個體使用 Amazon Aurora 資料庫叢集。

避免 Aurora MySQL 資料庫執行個體效能變慢、自動重新啟動和容錯移轉

如果您正在執行繁重的工作負載或工作負載超出資料庫執行個體配置的資源,則可能會在執行應用程式和 Aurora 資料庫時耗盡資源。若要取得資料庫執行個體的指標,例如 CPU 使用率、記憶體使用量和使用的資料庫連線數目,您可以參考 Amazon 提供的指標 CloudWatch、Performance Insights 和增強型監控。如需如何監控資料庫執行個體的詳細資訊,請參閱 在 Amazon Aurora 叢集中監控指標

如果您的工作負載耗盡了您正在使用的資源,您的資料庫執行個體可能會變慢、重新啟動,甚至容錯移轉到其他資料庫執行個體。若要避免這種情況,請監控資源使用率、檢查資料庫執行個體上執行的工作負載,並在必要時進行最佳化。如果最佳化無法改善執行個體指標並減緩資源耗盡,請考慮在達到其限制之前縱向擴展資料庫執行個體。如需可用資料庫執行個體類別及其規格的詳細資訊,請參閱 Aurora 資料庫執行個體類別

針對 Aurora MySQL 的建議

以下功能可在與 MySQL 相容的 Aurora MySQL 中使用。但是,這些功能在 Aurora 環境中存在效能、可擴展性、穩定性或相容性的問題。因此,建議您在使用這些功能時遵循某些指導方針。例如,建議您不要將特定功能用於生產 Aurora 部署。

在 Aurora MySQL 中使用多執行緒複寫

使用多執行緒二進位日誌複寫,SQL 執行緒會從轉送日誌讀取事件,並將它們排入佇列,以供 SQL 工作者執行緒套用。SQL 工作者執行緒是由協調器執行緒管理。可能的話,會平行套用二進位日誌事件。

Aurora MySQL 第 3 版和 Aurora MySQL 2.12.1 及更新版本中支援多執行緒複寫。

對於低於 3.04 的 Aurora MySQL 版本,當 Aurora MySQL 資料庫叢集用作二進位記錄複寫的僅供讀取複本時,依預設會使用單執行緒複寫。

早期版本的 Aurora MySQL 版本 2 繼承了有關從 MySQL 社區版多線程複製的幾個問題。對於這些版本,我們建議您不要在生產環境中使用多執行緒複寫。

如果您確實使用多執行緒複寫,建議您徹底測試它。

如需在 Amazon Aurora 中使用複寫的詳細資訊,請參閱以 Amazon Aurora 進行複寫。如需 Aurora MySQL 中多執行緒複寫的詳細資訊,請參閱多執行緒二進位記錄複寫

使用本地 MySQL AWS Lambda 函數調用函數

建議您使用原生 MySQL 函數 lambda_synclambda_async,以叫用 Lambda 函數。

如果您使用已棄用的 mysql.lambda_async 程序,建議在預存程序中包裝對 mysql.lambda_async 程序的呼叫。您可以從不同的來源 (例如觸發程式或用戶端程式碼) 呼叫此預存程序。此方法有助於避免阻抗不符問題,並讓您的資料庫程式設計人員能夠輕鬆呼叫 Lambda 函數。

如需從 Amazon Aurora 叫用 Lambda 函數的詳細資訊,請參閱從 Amazon Aurora MySQL 資料庫叢集叫用 Lambda 函式

避免搭配 Amazon Aurora MySQL 使用 XA 交易

建議您不要使用 eXtended Architecture (XA) 交易搭配 Aurora MySQL,因為如果 XA 處於 PREPARED 狀態,它們可能造成過長的復原時間。如果您必須使用 XA 交易搭配 Aurora MySQL,請遵循這些最佳實務:

  • 請勿讓 XA 交易保持開啟在 PREPARED 狀態。

  • 盡可能讓 XA 交易越小越好。

如需使用 XA 交易搭配 MySQL 的詳細資訊,請參閱 MySQL 文件中的 XA 交易

DML 陳述式期間保持外部索引鍵的開啟狀態

在將 foreign_key_checks 變數設為 0 (關閉) 時,強烈建議您不要執行任何資料定義語言 (DDL) 陳述式。

如果您需要插入或更新需要暫時違反外部索引鍵的資料列,請遵循這些步驟:

  1. foreign_key_checks 設定為 0

  2. 進行您的資料處理語言 (DML) 變更。

  3. 確定您完成的變更未違反任何外部索引鍵限制。

  4. foreign_key_checks 設為 1 (開啟)。

此外,遵循用於外部索引鍵限制的這些其他最佳實務:

  • 確定您的用戶端應用程式未隨著 foreign_key_checks 變數將 0 變數設為 init_connect

  • 如果從邏輯備份 (例如 mysqldump) 的還原失敗或未完成,在相同工作階段中開始任何其他操作之前,請確定將 foreign_key_checks 設為 1。邏輯備份會在開始時將 foreign_key_checks 設為 0

設定日誌緩衝區的排清頻率

在 MySQL Community Edition 中,若要使交易可以耐久,InnoDB 日誌緩衝區必須排清到耐久儲存。您可以使用 innodb_flush_log_at_trx_commit 參數來設定日誌緩衝區排清到磁碟的頻率。

當您將 innodb_flush_log_at_trx_commit 參數設為預設值 1 時,日誌緩衝區會在每次交易認可時進行排清。此設定有助於保持資料庫 ACID 合規。建議您保留預設設定 1。

變更innodb_flush_log_at_trx_commit為非預設值有助於減少資料操作語言 (DML) 延遲,但會犧牲記錄記錄的耐久性。一旦缺乏耐久性,就會使資料庫 ACID 不合規。建議您的資料庫必須是 ACID 合規,以避免在伺服器重新啟動時發生資料遺失的風險。如需此參數的詳細資訊,請參閱 MySQL 文件中的 innodb_flush_log_at_trx_commit

在 Aurora MySQL 中,重做日誌處理會卸載至儲存層,因此資料庫執行個體上不會排清至日誌檔。發出寫入時,重做日誌會從寫入器資料庫執行個體直接傳送至 Aurora 叢集磁碟區。唯一跨網路的寫入是重做日誌記錄。始終不會從資料庫層寫入任何頁面。

依預設,每個執行緒認可交易都會等待 Aurora 叢集磁碟區的確認。此確認指出已寫入此記錄和所有先前的重做日誌記錄,都已寫入並達到仲裁。不論是透過自動認可還是明確認可,持續保留日誌記錄並達到仲裁,都能使交易耐久。如需 Aurora 儲存架構的詳細資訊,請參閱 Amazon Aurora 儲存解密

Aurora MySQL 不會如 MySQL Community Edition 一樣將日誌排清到資料檔案。不過,在將重做日誌記錄寫入至 Aurora 叢集磁碟區時,您可以使用 innodb_flush_log_at_trx_commit 參數來放鬆耐久性限制。

對於 Aurora MySQL 版本 2:

  • innodb_flush_log_at_trx_commit= 0 或 2 — 資料庫不會等待重做日誌記錄寫入 Aurora 叢集磁碟區的確認。

  • innodb_flush_log_at_trx_commit= 1 — 資料庫會等待確認重做日誌記錄已寫入 Aurora 叢集磁碟區。

對於 Aurora MySQL 版本 3:

  • innodb_flush_log_at_trx_commit= 0 — 資料庫不會等待重做日誌記錄寫入 Aurora 叢集磁碟區的確認。

  • innodb_flush_log_at_trx_commit= 1 或 2 — 資料庫會等待確認重做日誌記錄已寫入 Aurora 叢集磁碟區。

因此,若要在 Aurora MySQL 第 3 版中取得與 Aurora MySQL 版本 2 中設定為 0 或 2 的相同非預設行為,請將參數設定為 0。

雖然這些設定可以降低用戶端的 DML 延遲,但在發生容錯移轉或重新啟動時,也可能導致資料遺失。因此,建議您將 innodb_flush_log_at_trx_commit 參數持續設定為預設值 1。

雖然 MySQL Community Edition 和 Aurora MySQL 都可能發生資料遺失,但由於其架構不同,每個資料庫的行為都會有所不同。這些架構差異可能會導致不同程度的資料遺失。若要確保您的資料庫是 ACID 合規,請將 innodb_flush_log_at_trx_commit 一律設定為 1。

注意

在 Aurora MySQL 版本 3 中,您必須先將值變更innodb_flush_log_at_trx_commit為 1 以外的值,才能變更innodb_trx_commit_allow_data_loss為 1。通過這樣做,您承認數據丟失的風險。

減少和疑難排解 Aurora MySQL 的死結情況

在相同資料頁面上並行修改記錄時,執行在唯一次要索引或外部索引鍵上經常遇到限制條件違規之工作負載的使用者,可能會遇到更多的死結情況和鎖定等待逾時。這些死結情況和逾時皆源自 MySQL Community Edition 錯誤修正

此修正包含在 MySQL Community Edition 5.7.26 及更新版本中,並已向後移植至 Aurora MySQL 2.10.3 及更新版本。強制序列化必須有此修正,方法是在 InnoDB 資料表的記錄變更上,針對這些資料處理語言 (DML) 類型執行額外鎖定。此問題是調查先前 MySQL Community Edition 錯誤修正導致的死結問題時發現的。

該項修正變更了 InnoDB 儲存引擎中,元組 (資料列) 更新的部分回復內部處理。在外部索引鍵或唯一次要索引產生限制條件違規的操作會導致部分回復。這包括但不限於並行 INSERT...ON DUPLICATE KEY UPDATEREPLACE INTO,INSERT IGNORE 陳述式 (upserts)。

在此情況下,部分回復並非應用程式層級交易的回復,而是發生限制條件違規時,對叢集索引的內部 InnoDB 回復變更。例如,在 upsert 操作期間找到重複索引鍵值。

在正常的插入操作中,InnoDB 會自動為每個索引建立叢集和次要索引項目。如果 InnoDB 在 upsert 操作期間偵測到唯一次要索引上的重複值,則叢集索引中插入的項目必須回復 (部分回復),並將更新套用至現有的重複列。在此內部部分回復步驟中,InnoDB 必須在操作中鎖定每個記錄。此修正會在部分回復之後引入額外鎖定,以確保交易序列化。

減少 InnoDB 死結情況

您可以採取下列方法來減少資料庫執行個體的死結情況發生頻率。MySQL 文件中有更多範例。

  1. 為了減少死結情況發生,請在進行一系列相關變更後立即遞交交易。您可以將大型交易 (遞交之間的多列更新) 拆解為較小交易來執行此動作。若您要批次插入行,請盡量減少批次插入的大小,尤其是使用上述提及的 upsert 操作時。

    若要減少部分回復的次數,您可以嘗試下列方法:

    1. 一次插入一行,而非進行批次插入操作。如此便能減少可能發生衝突之交易的鎖定時間。

    2. 請不要使用 REPLACE INTO,而是將 SQL 陳述式以多陳述式交易重新寫入,如下所示:

      BEGIN; DELETE conflicting rows; INSERT new rows; COMMIT;
    3. 請不要使用 INSERT...ON DUPLICATE KEY UPDATE,而是將 SQL 陳述式以多陳述式交易重新寫入,如下所示:

      BEGIN; SELECT rows that conflict on secondary indexes; UPDATE conflicting rows; INSERT new rows; COMMIT;
  2. 避免長時間執行且可能導致鎖定的作用中或閒置交易。其中包括互動式 MySQL 用戶端工作階段,這些工作階段可能會在未遞交的交易中長時間開啟。最佳化交易大小或批次大小時,影響會因並行、重複項目數量和資料表結構等因素而有所不同。任何變更都應根據您的工作負載來執行和測試。

  3. 在部分情況下,當兩筆交易嘗試以不同順序存取相同的資料集時,不論資料集是否位於同一個資料表,皆可能發生死結情況。為了防止這種情況,您可以修改交易以相同順序存取資料,進而序列化該存取。例如,建立待完成的交易佇列。當多個交易並行發生時,此方法便能協助避免死結情況。

  4. 將謹慎選擇的索引新增到資料表中,可改善選取性並減少存取資料列的需求,從而減少死結情況。

  5. 若發生間隙鎖定,您可以將工作階段或交易的交易隔離層級修改為 READ COMMITTED,以避免發生間隙鎖定。如需詳細了解 InnoDB 隔離層級和其行為,請參閱 MySQL 文件的交易隔離層級

注意

雖然您可以採取預防措施來減少死結情況,但死結情況是可預期的資料庫行為,仍然可能發生。應用程式應具有必要的邏輯來處理死結情況。例如,在應用程式中執行重試和停止邏輯。最理想的是解決問題根本原因,但是若確實發生死結情況,應用程式仍可以選擇等待並重試。

監控 InnoDB 死結情況

應用程式交易嘗試以導致循環等待的方式取得資料表層級和資料列層級鎖定時,MySQL 中可能發生死結。偶爾的 InnoDB 死結情況不一定是大問題,因為 InnoDB 儲存引擎會立即偵測到狀況,並自動復原交易。若您經常遇到死結情況,建議您檢閱和修改應用程式,以減緩效能問題並避免死結發生。當死結偵測開啟 (預設值) 時,InnoDB 會自動偵測交易死結,並復原交易以解決死結情況。InnoDB 嘗試選擇要復原的小型交易,而交易的大小是由插入、更新或刪除的資料列數而定。

  • SHOW ENGINE 陳述式 – SHOW ENGINE INNODB STATUS \G 陳述式包含自上次重啟以來,資料庫最近遇到的死結詳細資訊

  • MySQL 錯誤日誌 – 若您頻繁遇到死結,而 SHOW ENGINE 陳述式的輸出不敷使用,您可以開啟 innodb_print_all_deadlocks 資料庫叢集參數。

    開啟此參數時,InnoDB 使用者交易中所有死結的相關資訊皆會記錄在 Aurora MySQL 錯誤日誌

  • Amazon CloudWatch 指標 — 我們也建議您使用指標主動監控死 CloudWatch 結Deadlocks。如需詳細資訊,請參閱 Amazon Aurora 的執行個體層級指標

  • Amazon CloudWatch 日誌 — 使用 CloudWatch 日誌,您可以檢視指標、分析日誌資料以及建立即時警示。如需詳細資訊,請參閱使用 Amazon 監控 Amazon Aurora MySQL 中的錯誤 CloudWatch 和使用 Amazon SNS 傳送通知

    使用 CloudWatch 記錄開innodb_print_all_deadlocks啟時,您可以設定警示,以便在死結數超過指定臨界值時通知您。若要定義閾值,建議您觀察平時情況,根據您的正常工作負載來定義該值。

  • 績效詳情 — 當您使用績效詳情時,您可以監控 innodb_deadlocksinnodb_lock_wait_timeout 指標。如需這些指標的詳細資訊,請參閱 Aurora MySQL 的非原生計數器