地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【MySQL】trx_sys->mutexは人気のmutex

MySQLでtrx_sys->mutexは色々な箇所から呼び出されている。これを長時間保持してるトランザクションがあるとMySQL全体の性能ダウンに繋がるというお話。

まとめ

  • trx_sys->mutexはトランザクションの開始/終了時にも確保する必要がある
  • 長時間保持して解放しないスレッドがいると他トランザクションの処理が進まないという状態になる
  • 長時間保持するようなケースは実行頻度を減らすか代替案があればそちらを使用するにして回避する

詳細

github.com

実装自体はこんな感じ

github.com

InnoDBSQLを実行する際はトランザクションで実行されます。各トランザクションが開始された後、そのトランザクションをグローバル トランザクション リストに追加する必要があり、グローバル トランザクション リストは trx_sys->mutex ミューテックスによって保護される必要があります。

/** Starts a transaction. */
static void trx_start_low(
    trx_t *trx,      /*!< in: transaction */
    bool read_write) /*!< in: true if read-write transaction */
{
    if (!trx_is_autocommit_non_locking(trx)) { // 自動コミットモードじゃないかつ非ロッキング読み取りクエリ
      /* If this is a read-only transaction that is writing
      to a temporary table then it needs a transaction id
      to write to the temporary table. */

      if (read_write) {
        trx_sys_mutex_enter();

        ut_ad(!srv_read_only_mode);

        trx->state.store(TRX_STATE_ACTIVE, std::memory_order_relaxed);

        trx->id = trx_sys_allocate_trx_id();

        trx_sys->rw_trx_ids.push_back(trx->id);

        trx_sys_mutex_exit();

        trx_sys_rw_trx_add(trx);

      } else {
        trx->state.store(TRX_STATE_ACTIVE, std::memory_order_relaxed);
      }

このコードは、MySQLデータベースのInnoDBストレージエンジン内部でトランザクションを開始するための関数trx_start_lowの実装を示しています。この関数は、新しいトランザクションを開始する際に、トランザクションオブジェクトの初期化や状態の更新など、いくつかの重要なステップを行います。以下に、コードの主要な部分を説明します。

github.com