並列イベント実行(マルチスレッドレプリカ)
- NDBレプリケーション:NDB Clusterレプリケーションは、レプリカサーバーでMySQLマルチスレッドアプライヤー(MTA)をサポートするようになりました。これにより、バイナリログトランザクションをレプリカに並行して適用できるようになり、ピーク時のレプリケーションスループットが向上します。レプリカでこれを有効にするためには、次の手順を実行する必要があります:
- このリリースで追加された--ndb-log-transaction-dependencyオプションをONに設定します。これは、ソース上のmysqldの起動時に行う必要があります。
- binlog_transaction_dependency_trackingサーバーシステム変数を、これもソース上で、WRITESETに設定します。これにより、トランザクションの依存関係がソースで決定されます。これは実行時に行うことができます。
- レプリカが複数のワーカースレッドを使用していることを確認してください。これは、NDBが受け入れるようになったreplica_parallel_workersサーバーシステム変数の値によって決定されます(以前は、NDBはこの変数に設定された値を事実上無視していました)。デフォルトは4で、実行時にレプリカで変更できます。
--binlog-transaction-dependency-history-sizeオプションを使用して、トランザクションの依存関係の履歴をソース上に保存するために使用されるバッファのサイズを調整できます。また、ソースでは、replica_parallel_typeをLOGICAL_CLOCK(デフォルト)に設定する必要があります。
さらに、レプリカでは、replica_preserve_commit_orderをON(デフォルト)にする必要があります。
(バグ #27960、バグ #11746675、バグ #35164090、バグ #34229520、WL #14885、WL #15145、WL #15455、WL #15457)
追加・変更された機能
- NDB Cluster API:MySQL NoSQL Connector for JavaScriptの構築に使用されるNode.jsライブラリがバージョン 18.12.1にアップグレードされました。(バグ #35095122)
- MySQL NDB ClusterJ:カラムのタイプがCHARまたはVARCHARの場合に、単一カラムのパーティションキーを使用してテーブルにアクセスする際のパフォーマンスが向上しました。(バグ #35027961)
- このリリース以降、ndb_restoreは--timestamp-printoutsオプションを実装します。これにより、全てのエラー、情報、デバッグノードログメッセージにタイムスタンプがプレフィックスとして付けられます。(バグ #34110068)
主なバグ修正
- Microsoft Windows:コードインスペクションで見つかった2つのメモリリークが、WindowsプラットフォームのNDBプロセスハンドルから削除されました。(バグ #34872901)
- Microsoft Windows:Windowsプラットフォームで、データノードエンジェルプロセスは、子データノードプロセスが正常に終了したかどうかを検出しませんでした。これを解決するために、開いているプロセスハンドルを子に保持し、子の終了をプローブする時にこれを使用します。(バグ #34853213)
- NDBレプリケーション:マルチスレッドアプライヤーを使用する場合、ndb.apply_statusテーブルのstart_pos列とend_pos列に正しい位置情報が含まれていませんでした。(バグ #34806344)
- NDB Cluster API:MySQL NDB ClusterJ:MySQL ClusterJはプライマリキーのハッシュ計算にスクラッチバッファを使用しますが、これは10000バイトに制限されており、場合によっては小さすぎることが判明しました。バッファのサイズが十分でない場合は、バッファを malloc()するようにしました。
これにより、NDB APIのNdbオブジェクトメソッド startTransaction()およびcomputeHash()の問題も修正されます。以前は、これらのメソッドのいずれかに不十分なサイズの一時バッファが渡されると、メソッドが失敗しました。このような場合、一時バッファが割り当てられます。
(バグ #103814、バグ #32959894) - NDB Cluster API:NDB APIでイベント操作(NdbEventOperation)をドロップすると、このイベント操作に関連するイベントの送信を停止するようにデータノードに指示した後、保留中のバッファリングされた全てのイベントが消費され破棄される前に、ドロップされたイベント操作がアプリケーションに表示されたままになることがありました。これは、ADD COLUMNやRENAME COLUMNなどのオンラインの変更操作を、影響を受けるテーブルへの同時書き込みと共に実行する場合に、特定のケースで見られる可能性があります。
さらに分析を行うと、Ndb::getGCIEventOperations()を使用してイベント操作を繰り返すと、ドロップされたイベントにアクセスできることがわかりました。現在、このメソッドは繰り返し呼び出された時にドロップされたイベントをスキップします。(バグ #34809944) - NDB Cluster API:Event::getReport()は、レポートオブジェクトによって実際に使用されるフラグを返す代わりに、NDBから開かれたイベントに対して常にER_UPDATEDを返しました。(バグ #34667384)
- 新しいNDBテーブル定義をデータディクショナリに格納する前に、既存の定義を削除する必要があります。テーブル定義には、テーブル名とNDB Cluster se_private_idという2つの一意の値があります。新しいテーブル定義のインストール中に、同じテーブル名の既存の定義があるかどうかを確認し、存在する場合は削除します。次に、削除されたテーブルとインストールされたテーブルのse_private_idが同じかどうかを確認します。違う場合、このse_private_idを占有している定義は古いと見なされ、同様に削除されます。
se_private_idが占有されていても定義が削除されないため、テーブルの名前を使用した検索で既存の定義が見つからない場合に問題が発生しました。これにより、新しいテーブルを保存しようとすると、重複キーエラーが発生しました。内部のstore_table()関数は、診断領域をクリアし、se_private_idの古い定義を削除して、もう一度格納しようとしましたが、診断領域は実際にはクリアされていなかったため、エラーがリークされ、それがユーザーに表示されます。
これを修正するために、store_table()によって実行された(または実行されなかった)アクションに関係なく、古いテーブル定義を削除します。(バグ #35089015) - ndb_restoreの出力で次の2つの問題を修正しました:
- バックアップファイル形式のバージョンと、バックアップを作成したクラスターのバージョンの両方について、バックアップファイル形式のバージョンが表示されました。
- ファイル形式のバージョンとバックアップを作成したクラスターのバージョンとの間の混乱を減らすために、バックアップファイル形式のバージョンが16進表記を使用して表示されるようになりました。
(バグ #35079426)
参照:この問題はバグ #34110068 のリグレッションです。 - 内部外部キー定義レコードが不要になった時に解放されなかった場合に発生したDBDICTカーネルブロックでのメモリリークが削除されました。これは、次のいずれかのイベントによってトリガーされる可能性がありました:
- NDBテーブルでの外部キー制約のドロップ
- NDBテーブルに外部キー制約を作成しようとする試みの拒否
このようなレコードは、DISK_RECORDSメモリリソースを使用します。mysqlクライアントでSELECT node_id, used FROM ndbinfo.resources WHERE resource_name='DISK_RECORDS'を実行することにより、実行中のクラスターでこれを確認できます。このリソースはSharedGlobalMemoryを使用します。これが枯渇すると、外部キーの作成の試行が拒否されるだけでなく、結合を使用するクエリも拒否される可能性があります。これは、DBSPJブロックもQUERY_MEMORYを介して共有グローバルメモリを使用するためです。(バグ #35064142)
- --ndb-allow-copying-alter-table = OFFでコピーの変更操作を試行すると、ステートメントが拒否される理由が常にユーザーに明確に示されるとは限りませんでした。(バグ #35059079)
- トランザクションコーディネーターがスキャンする多数のフラグメントを使用してフラグメントスキャンを開始している場合、プロセス中にリアルタイムブレーク(RTB)をとって、他の要求に対する公平なCPUアクセスを確保する場合があります。RTB継続が返される前に、要求元のAPIが切断され、スキャン状態のAPIエラー処理が発生した場合、スキャン状態が削除されたために、継続処理が続行できませんでした。
継続プロセスの一部としてスキャン状態に適切なチェックを追加することで、これを修正します。(バグ #35037683) - 送信者と受信者のシグナルIDは、実際には符号なしの32ビットの数値であるにもかかわらず、符号付きの値としてトレースログに出力されました。これにより、最上位ビットが設定された時に、-MAX_32_BIT_SIGNED_INTから上に数えて、そのような数値が負として表示されるため、混乱が生じる可能性がありました。(バグ #35037396)
- DICTブロックによって使用されるファイバーは、全てのインデックスを監視し、DBTUXインデックスフラグメントモニタリングによって要求された場合、インデックス統計の計算をトリガーします。これらの計算は、スキーマトランザクションを使用して実行されます。DICTファイバーがスキーマトランザクションの開始を要求するためのトランザクションハンドルを取得しようとして失敗した場合、ファイバーが終了したため、ノードの障害なしでインデックス統計の自動更新を実行できませんでした。(バグ #34992370)
参照:バグ #34007422も参照してください。 - NDBのスキーマオブジェクトは、メジャーサブバージョンとマイナーサブバージョンで構成される複合バージョン管理を使用します。スキーマオブジェクトが最初に作成されると、そのメジャーバージョンとマイナーバージョンが設定されます。既存のスキーマオブジェクトが適切に変更されると、そのマイナーサブバージョンがインクリメントされます。
再起動時に、各データノードはリカバリの一部としてスキーマオブジェクトをチェックします。外部キーオブジェクトの場合、参照される親テーブルと子テーブル(および、テーブルのプライマリキーへではない、または、テーブルのプライマリキーからではない外部キー参照用のインデックス)のバージョンの整合性がチェックされます。このチェックのテーブルバージョンはメジャーなサブバージョンのみを比較し、テーブルを進化させますが、インデックスバージョンはマイナーなサブバージョンも比較します。これにより、インデックスが変更された時に再起動時にエラーが発生しました。
このような場合、インデックスのメジャーサブバージョンのみを比較することでこれを修正します。(バグ #34976028)
参照:バグ #21363253も参照してください。 - ndb_importは、大きなVARCHARプライマリキーを持つテーブルのヒントの失敗を黙って無視することがありました。どのトランザクションコーディネーターを使用するかを示唆するために、ndb_importは、キーのハッシュを計算するために4092バイトのバッファーを使用して、行のパーティショニングキーを使用できます。
キーにUTF8を使用するVARCHAR列が含まれている場合、これは問題でした。これは、列の照合に応じて、ハッシュバッファが列の最大文字数の24倍のバイト数を必要とする可能性があるためです。ハッシュ計算は失敗しましたが、ndb_importの呼び出しコードはこれをチェックせず、未定義のヒントを生成する未定義のハッシュ値を使用し続けました。
これは機能上の問題にはつながりませんでしたが、最適ではありませんでした。そして、ユーザーには通知されませんでした。
ndb_importがキー内の文字列(照合順序に関係なく)を処理するために常に十分なバッファを使用するようにし、ハッシュ計算の失敗についてndb_importにチェックを追加し、ユーザーに報告することで、これを修正します。(バグ #34917498) - ndbclusterプラグインがndb_schemaテーブルを作成すると、プラグインはメタデータを含む行を挿入します。この行は、このNDB Clusterインスタンスを追跡するために必要であり、このテーブルの行にキーと値のペアのセットとして格納されます。
ndb_schemaテーブルはMySQLから隠されているため、SQLを使用してクエリを実行することはできませんが、ndb_schemaテーブルを作成する同じMySQLサーバーによって生成されたUUIDが含まれています。ndb_schemaテーブルがインストールされると、同じUUIDが各MySQLサーバーのデータディクショナリにメタデータとして格納されます。
mysqldがNDBに接続(または再接続)すると、同じクラスターに再接続しているかどうかを検出するために、独自のデータディクショナリのUUIDとNDBに格納されているUUIDを比較します。同じでない場合は、NDBから新しい全てのテーブルをより速く簡単にインストールできるようにするために、データディクショナリの内容全体が破棄されます。
このようなケースの1つは、全てのNDBデータノードが--initialを使用して再起動され、全てのデータとテーブルが削除された場合に発生します。ndb_schemaテーブルがそのデータを復元せずにバックアップから復元された場合、別のことが発生します。これは、ndb_schemaテーブルの行が失われることを意味するためです。
このような状況に対処するために、現在は、同期が完了すると、MySQLサーバーのデータディクショナリに格納されているUUIDと一致するUUIDを持つ行がNDBディクショナリに常に存在するようになりました。(バグ #34876468) - 複数の管理サーバーでNDB Clusterを実行している場合、クラスターのシャットダウン時にndb_mgmdプロセスの終了に非常に長い時間がかかりました。(バグ #34872372)
- 次のスキーマ操作が開始された時に、事前にサブスクライブされたノードがまだ再サブスクライブされていない場合、mysql.ndb_schemaテーブルを削除して再作成した後、スキーマ配布タイムアウトがスキーマ配布コーディネーターによって検出されました。これは、スキーマ配布データに取り残されているサブスクライバーの古いリストが原因でした。これらのサブスクライバーは、コーディネーターによって後続のスキーマ操作の参加者であると想定されていました。
mysql.ndb_schemaテーブルがドロップされる度に、既知のサブスクライバーのリストをクリアすることで、この問題を修正します。(バグ #34843412) - スキーマ配布イベントと応答の配信を高速化するために、mysqldのNDB Clusterハンドラなどによってデータノードから新しいグローバルチェックポイント(GCP)を要求すると、要求が100回送信されました。DBDIHブロックはこれらの重複するリクエストを1つにマージしようとしましたが、場合によっては複数の即時GCPをトリガーすることができました。(バグ #34836471)
- DBSPJブロックは、実行するクエリを受け取ると、実行方法に関する独自の内部プランを設定します。このプランは、オプティマイザによって提供されるクエリプランに基づいており、経過時間と使用される合計リソースの両方に関して、クエリを最も効率的に実行できるように調整されています。
DBSPJが受け取るクエリプランには、次のクエリのように、いくつかの子テーブルが共通の親に依存するスター結合が含まれていることがよくあります:SELECT STRAIGHT_JOIN * FROM t AS t1
INNER JOIN t AS t2 ON t2.a = t1.k
INNER JOIN t AS t3 ON t3.k = t1.k;このような場合、DBSPJはキー範囲ルックアップをt2とt3に並行して送信できます(ただし、そうはしません)。内部結合には、内部結合された各行が同じ結合ネスト内の他のテーブルからの一致を必要とするというプロパティもあり、そうでない場合、行は結果セットから削除されます。したがって、キー範囲ルックアップを使用することで、1つのルックアップから他のルックアップに一致しない行を取得することができますが、この努力は最終的に無駄になります。代わりに、DBSPJはそのようなクエリのシーケンシャルプランを設定します。
これは、内部結合のみを持つクエリでは意図したとおりに機能することがわかりましたが、テーブルのいずれかが左結合されている場合、外部結合されたテーブルを発行する前に、前の内部結合テーブルを完全に利用していませんでした。次のように、前のクエリが左結合を含むように変更されたとします:
SELECT STRAIGHT_JOIN * FROM t AS t1
INNER JOIN t AS t2 ON t2.a = t1.k
LEFT JOIN t AS t3 ON t3.k = t1.k;ndbinfo.countersテーブルに対して次のクエリを使用すると、クエリ実行の前後に各クエリで返される行数を確認できます:
SELECT counter_name, SUM(val)
FROM ndbinfo.counters
WHERE block_name="DBSPJ" AND counter_name = "SCAN_ROWS_RETURNED";この結果として、t2とt3の要求が並行して送信されたと判断されました。現在は、このような場合、t1からの一致しない行をt1とt3の外部結合から削除できるように、左結合を発行する前に内部結合が完了するのを待ちます。これにより、データノードによって実行される作業が減り、トランスポーターによって処理される量も減少します。(バグ #34782276)
- ソートされた結果のSPJ処理は、ソートされていない場合の同じ結果セットと比較して、パフォーマンスに大きな影響を与えることが判明しました。さらに調査した結果、ソートされた結果の追加のパフォーマンスオーバーヘッドのほとんどは、ソートされた結果の取得の実装にあることがわかりました。実装には、データノード上のクライアントとDBSPJの間で過剰な回数のSCAN_NEXTREQラウンドトリップが必要でした。(バグ #34768353)
- DBSPJは、EXISTSおよびNOT EXISTSサブクエリに見られるものなど、セミジョインおよびアンチジョインのfirstMatch最適化を実装するようになりました。(バグ #34768191)
- DBSPJブロックがSCAN_FRAGREQ信号とSCAN_NEXTREQ信号をデータノードに送信すると、使用可能なバッチバッファを満たすために必要な数以上の並列スキャンを開始することなく、並列でスキャンするフラグメントの最適な数を決定しようとします。したがって、各フラグメントのスキャンを完了するために追加のSCAN_NEXTREQシグナルを送信する必要がなくなります。
DBSPJブロックの統計モジュールは、完了したSCAN_FRAGREQごとに、完了したばかりのフラグメントスキャンに最適な並列処理を計算してサンプリングし、サンプリングされた並列処理の平均偏差と標準偏差を提供します。これにより、並列処理(およびバッチサイズ)の下位95パーセンタイルを計算できるため、追加のSCAN_NEXTREQ信号を必要とせずにSCAN_FRAGREQを完了することができます。
並列処理の統計は安定した並列処理の見積もりを提供できないようであり、標準偏差が予想外に高いことがわかりました。これにより、並列処理の見積もりが負の数になることがよくありました(常に1に切り上げられます)。
統計計算の欠陥は、サンプリングされた各SCAN_FRAGREQにスキャンされるキー範囲が同じ数含まれているという根本的な仮定であることが判明しましたが、これは必ずしもそうではありません。通常は、最初のSCAN_FRAGREQの行の完全なバッチと、残りの行を返す最後のSCAN_NEXTREQの比較的少数の行。これにより、並列処理のサンプルに大きなばらつきが生じ、それらから得られた統計が信頼できなくなりました。
SCAN_FRAGREQで実際に送信されたキーの数に基づいて統計を作成し、このリクエストから返された行をカウントすることで、これを修正します。これに基づいて、キーごとのレコード統計を取得し、計算してサンプリングすることができます。これにより、バッチバッファをオーバーフローさせることなく、スキャンできるフラグメントの数を計算できます。(バグ #34768106) - 特定のケースでは、NDBバイナリロギングスレッドとメタデータ同期の両方がndb_apply_statusテーブルの同期を試み、競合状態が発生する可能性がありました。ndb_apply_statusテーブルがバイナリロギングスレッドによってのみ監視および作成(または再作成)されるようにすることで、これを修正します。(バグ #34750992)
- スキーマ操作の開始中、コーディネーターが最初のスキーマイベントを受信する(その時点からは、コーディネーターがスキーマ操作のタイムアウトを検出する必要があります)まで、クライアントはタイムアウトを検出する責任があります。クライアントがタイムアウトをチェックしている時に問題が発生しました。タイムアウトが発生したことを示す状態を誤って設定したため、コーディネーターは、受信(つまり、バイナリログスレッドでの送信イベントとハンドルの書き込み)に約1秒以上かかる最初のスキーマイベントを無視しました。これは、これらの場合、コーディネーターがスキーマ操作に関与しないという効果がありました。
これを修正するために、スキーマ配布のタイムアウトチェックをアトミックに変更し、クライアントまたはコーディネーターのいずれかで実行できるようにします。さらに、コーディネーターが受信したイベントを追跡するために使用される状態変数を削除し、代わりに参加者のリストに依存します。(バグ #34741743) - ndb_restoreを使用してデータを復元した後、SQLノードが正しく起動しませんでした。それ以外の場合は接続を受け入れる準備ができていても、バイナリログインジェクタスレッドの準備ができていませんでした。新しいテーブル IDが生成されたデータノードの初期復元後にmysqldが開始されると、ユーティリティテーブルの(ndb_*) MySQLデータディクショナリ定義がNDBディクショナリ定義と一致しない場合があることが判明しました。
既存のmysqld定義は名前によってドロップされるため、MySQLデータディクショナリ内の一意のndbcluster-IDキーが削除されますが、新しいテーブル IDは別の(古い)定義によって既に占有されている可能性があります。結果として生じる不一致により、バイナリログのセットアップが妨げられました。
この問題を修正するために、インストールされているテーブルとこのような場合に衝突する可能性のあるndbcluster-ID定義を明示的にドロップするようになりました。(バグ #34733051) - SIGTERMシグナルを受信した後、ndb_mgmdは終了する前に全てのスレッドがシャットダウンするのを待ちませんでした。(バグ #33522783)
参照:バグ #32446105も参照してください。 - 1つの行で複数の操作が保留している場合、アボートが保留中の操作と同時に実行される操作をコミットすることはできません。これにより、DBACCでのコミット操作中にデータノードがシャットダウンする可能性があり、1つのトランザクションにMaxDMLOperationsPerTransactionを超えるDML操作が含まれている場合に発生する可能性がありました。
さらに、DML操作が多すぎるために、準備された挿入でロックスキャンを使用するステートメントが失敗した場合、挿入操作を含むトランザクションはロールバックされます。これにより、予想されるDBLQH割り当て解除操作への参照が欠落しているため、タプルの割り当て解除中に予定外のデータノードのシャットダウンが発生する可能性がありました。
トランザクション中に以前に取得したロックを解放するために、このような場合にスキャン操作のコミットを許可することによって、この問題を解決します。また、割り当て解除が単一フェーズで実行され、DBACCがDBLQHにすぐに割り当て解除するように指示するように、このシナリオに新しい特殊なケースを追加します。DBLQHでは、execTUP_DEALLOCREQ()がこの即時割り当て解除要求を処理できるようになりました。(バグ #32491105)
参照:バグ #28893633、バグ #32997832も参照してください。 - クラスターノードは、実際には必要ない場合でも、Failed to convert connection to transporterという警告をログに報告することがありました。(バグ #14784707)
- コマンドラインで接続文字列を指定せずに開始すると、ndb_waiterはConnecting to mgmsrv at (null)を出力しました。このような場合、他のデフォルトホストが指定されていなければ、Connecting to management server at nodeid=0,localhost:1186が出力されます。
--helpオプションとその他のndb_waiterプログラムの出力も改善されました。(バグ #12380163) - NdbSpin_Init()は、NdbSpinで誤った数のループを計算し、論理エラーを含んでいました。(バグ #108448、バグ #32497174、バグ #32594825)
参照:バグ #31765660、バグ #32413458、バグ #102506、バグ #32478388も参照してください。
全ての変更点やバグ修正については、以下のページをご覧ください。
MySQL NDB Cluster 8.0.33リリースノート(MySQLウェブサイト):
https://dev.mysql.com/doc/relnotes/mysql-cluster/8.0/en/news-8-0-33.html
MySQL Editions
MySQLのサブスクリプションは、24時間365日体制でお客様をサポートいたします。さらに MySQL Enterprise Edition では、データベース管理者支援ツール MySQL Enterprise Monitor やバックアップツール MySQL Enterprise Backup をご利用いただけます。