スキーム:
-- 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;