以下は、FOR UPDATE intention lockの簡単な例です。 INNODBエンジンによる行レベルのロック。このサンプルでは、よく知られているINNODB Gap Anomaly(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
またはbloatyコードを持っていません。意味、使用する次のシーケンスを取得し、更新(増分部分)、COMMIT
、、ASAPを実行します。
ストアドプロシージャ上記は:
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
ようのみ1 2つのメカニズムを有するあなたのニーズのために応じてストアドプロシージャを変更しますシーケンス番号(OUTパラメーターまたは結果セットのいずれか)を検索します。言い換えると、OUT
のパラメータの概念を簡単に破棄することができます。
LOCKのASAPリリース(更新後には明らかに不要)を遵守せず、リリース前に時間のかかるコードを実行し続けると、他のタイムアウト期間の後に次のことが起こりますシーケンス番号を待つクライアント:
ERROR 1205(HY000):ロック待ちタイムアウトを超えました。再起動してください トランザクション
これは決して問題ではありません。
show variables where variable_name='innodb_lock_wait_timeout';
MySQLマニュアルページinnodb_lock_wait_timeout。
現在私のシステムでは、値は50(秒)です。ほとんどの状況では、おそらく1秒以上2秒以上の待ち時間は耐えられません。トランザクション中
また、関心の次のコマンドからの出力のセクションです:
SHOW ENGINE INNODB STATUS;
ことを明確にするシーケンスとしてあなたの心にあるものの例を与えます。そして、なぜあなたがストアドプロシージャでこれを自分で行うことができないのかを説明してください。 – Drew