sql >> データベース >  >> RDS >> Mysql

mysql-Oracleのシーケンスに似たメカニズムを作成する

    以下は、FOR UPDATE インテンションロック<の簡単な例です。 / a> 。 INNODBエンジンによる行レベルのロック。サンプルは、よく知られているINNODBギャップ異常(AUTO_INCREMENTの使用に失敗した後にギャップが発生する場合)の影響を受けない、次に利用可能なシーケンスの4つの行を示しています。

    スキーム:

    -- drop table if exists sequences;
    create table sequences
    (   id int auto_increment primary key,
        sectionType varchar(200) not null,
        nextSequence int not null,
        unique key(sectionType)
    ) ENGINE=InnoDB;
    
    -- truncate table sequences;
    insert sequences (sectionType,nextSequence) values
    ('Chassis',1),('Engine Block',1),('Brakes',1),('Carburetor',1);
    

    サンプルコード:

    START TRANSACTION; -- Line1
    SELECT nextSequence into @mine_to_use from sequences where sectionType='Carburetor' FOR UPDATE; -- Line2 
    select @mine_to_use; -- Line3
    UPDATE sequences set nextSequence=nextSequence+1 where sectionType='Carburetor'; -- Line4
    COMMIT; -- Line5
    

    理想的には、Line3がありません または、ロック待機で他のクライアントを遅らせるような肥大化したコード。つまり、使用する次のシーケンスを取得し、更新(インクリメント部分)を実行して、COMMITできるだけ早く

    ストアドプロシージャの上記:

    DROP PROCEDURE if exists getNextSequence;
    DELIMITER $$
    CREATE PROCEDURE getNextSequence(p_sectionType varchar(200),OUT p_YoursToUse int)
    BEGIN
        -- for flexibility, return the sequence number as both an OUT parameter and a single row resultset
        START TRANSACTION;
        SELECT nextSequence into @mine_to_use from sequences where sectionType=p_sectionType FOR UPDATE;
        UPDATE sequences set nextSequence=nextSequence+1 where sectionType=p_sectionType;
        COMMIT; -- get it and release INTENTION LOCK ASAP
        set [email protected]_to_use; -- set the OUT parameter
        select @mine_to_use as yourSeqNum; -- also return as a 1 column, 1 row resultset
    END$$
    DELIMITER ;
    

    テスト:

    set @myNum:= -1;
    call getNextSequence('Carburetor',@myNum);
    +------------+
    | yourSeqNum |
    +------------+
    |          4 |
    +------------+
    select @myNum; -- 4
    

    シーケンス番号(OUTパラメータまたは結果セット)を取得するための2つのメカニズムのうち1つだけを使用するなど、必要に応じてストアドプロシージャを変更します。言い換えれば、OUTを捨てるのは簡単です パラメータの概念。

    LOCKのASAPリリース(更新後には明らかに不要)に準拠せず、リリース前に時間のかかるコードの実行に進むと、シーケンスを待機している他のクライアントのタイムアウト期間後に次のことが発生する可能性があります番号:

    エラー1205(HY000):ロック待機タイムアウトを超えました。トランザクションを再開してみてください

    うまくいけば、これが問題になることはありません。

    show variables where variable_name='innodb_lock_wait_timeout';
    

    innodb_lock_wait_timeout のMySQLマニュアルページ 。

    現在の私のシステムでは、50(秒)の値があります。ほとんどの場合、1〜2秒以上待つのは耐えられないでしょう。

    また、TRANSACTIONS中に重要なのは、次のコマンドからの出力のそのセクションです。

    SHOW ENGINE INNODB STATUS;
    



    1. SQL、結果を連結する方法は?

    2. SQL Serverで日時フィルタリングのパフォーマンスを向上させる方法は?

    3. SQLiteの文字列に改行を挿入する2つの方法

    4. AmazonRDSポイントインタイムリカバリとClusterControlの比較