1

テーブルの変更中に使用しているストアド プロシージャがあり、次のエラー メッセージで失敗します。

エラー 1206 (HY000): ロックの総数がロック テーブルのサイズを超えています

私は Web を調べて、ここと mysql フォーラムでエントリを見つけました。コンセンサスは、innodb_buffer_pool_size のサイズを大きくするか、1 回のアクションで追加/変更されるレコードの数を減らすことです。

残念ながら、innodb_buffer_pool_size を増やすオプションや機能がないため、アクションごとに変更されるレコードの数を減らそうとしています。しかし、それも失敗しています。

次の 2 つの列を持つ単純な時間分割テーブル event_notify_occurrence_cache がありました。

CREATE TABLE `event_notify_occurrence_cache` (
`timestamp` datetime NOT NULL,
`xml` text NOT NULL,
KEY `idx_timestamp` (`timestamp`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50500 PARTITION BY RANGE COLUMNS(`timestamp`)
(PARTITION p2012_12_10__15_00_00UTC VALUES LESS THAN ('2012-12-10 16:00:00') ENGINE = InnoDB,
PARTITION p2012_12_10__16_00_00UTC VALUES LESS THAN ('2012-12-10 17:00:00') ENGINE = InnoDB,
...
...
...

これを変更して「イベント タイプ」列を作成する必要があります。ここで、イベント タイプは xml 列の文字列の一部です。「LIKE」検索を実行すると著しく遅いため、イベント タイプ用に別のインデックス付き列を追加します。以下に変更したいと思います。

CREATE TABLE `event_notify_occurrence_cache` (
`event_type_value` smallint(5) unsigned NOT NULL,
`timestamp` datetime NOT NULL,
`xml` text NOT NULL,
KEY `idx_timestamp` (`timestamp`),
KEY `idx_event_type_value` (`event_type_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50500 PARTITION BY RANGE COLUMNS(`timestamp`)
(PARTITION p2012_12_10__15_00_00UTC VALUES LESS THAN ('2012-12-10 16:00:00') ENGINE = InnoDB,
PARTITION p2012_12_10__16_00_00UTC VALUES LESS THAN ('2012-12-10 17:00:00') ENGINE = InnoDB,
...
...

これに一致するようにテーブルを変更すると、event_type_value 列に、期待どおりに、無効なイベント タイプ ゼロ (0) が入力されます。

これまでのところ、これはすべて機能します。

したがって、次のステップは、基本的に次のようなロジックを使用して、考えられるイベントの種類ごとにテーブルで一連の更新を行うことです。

UPDATE event_notify_occurrence_cache
SET event_type_value = 1
WHERE event_type_value = 0 AND xml LIKE "%<eventType>1</eventType>";

考えられるイベントの種類ごとにこれを繰り返します。

これは、最初の一致が約 201,827 レコードにヒットする、合計 9,110,000 レコードの 24 のパーティションがあるテスト ケースの 1 つでは失敗します。

特定のイベント タイプのすべてのエントリが完了するまでLIMIT、句を含むステートメントを使用してループしようとしましたが、うまくいきません。UPDATE

最初に 5000 の制限で試しましたが、150,000 レコード後に失敗しました (デバッグ出力による)。次に、制限を 1000 に設定すると、152,000 レコードを超えると失敗します。その後の試行で、UPDATE句をTRANSACTION/のCOMMITペアでラップしたところ、エラーになる前に 182,000 レコードになりました。

ロック テーブルがステートメントごとではなく、ストアド プロシージャごとにあるようです。

1 つのスタックオーバーフローの回答では、書き込み対象のテーブルをロックすることが提案されました。「LOCK TABLE」コマンドを使用してみましたが、それでも機能しませんでした。

サーバー バージョン 5.5.8-enterprise-commercial-advanced-log を使用しています

私のストアドプロシージャロジックの試みの1つの例は次のとおりです

....
OPEN etype;
REPEAT
    FETCH etype INTO etype_name, etype_value;

    IF done != 1 THEN
        SET query_str :=
        CONCAT('%<eventType>', etype_name, '</eventType>%');

        SET changes_not_done := 1;
        WHILE changes_not_done != 0 DO

            SELECT CONCAT(CURRENT_TIMESTAMP(), ' ETYPE:', etype_name,
                ' CHANGES_NOT_DONE:', changes_not_done)
                AS 'Debug Msg:';


            UPDATE `UMS`.`event_notify_occurrence_cache`
                SET event_type_value=etype_value
                WHERE event_type_value=0 AND xml LIKE query_str
                LIMIT 1000;

            -- set changes_not_done to the number of rows modified by the
            -- previous command. If it's zero, then we are done. If it's
            -- non-zero then we have more to do.
            SELECT ROW_COUNT() INTO changes_not_done;

        END WHILE;
    END IF;

UNTIL done = 1
END REPEAT;
CLOSE etype;
...

イベント タイプのテーブルがあり、それをループし、イベント タイプごとに通知キャッシュを検索して処理します。

よろしくお願いいたします。

4

0 に答える 0