Berikut ini adalah contoh sederhana dengan FOR UPDATE intention lock . Kunci tingkat baris dengan mesin INNODB. Sampel menunjukkan empat baris untuk urutan berikutnya yang tersedia yang tidak akan mengalami Anomali Celah INNODB yang terkenal (kasus di mana celah terjadi setelah penggunaan AUTO_INCREMENT yang gagal).
Skema:
-- 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);
Contoh kode:
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
Idealnya Anda tidak memiliki Line3
atau kode kembung sama sekali yang akan menunda klien lain pada Lock Wait. Artinya, dapatkan urutan berikutnya untuk digunakan, lakukan pembaruan (bagian yang bertambah), dan COMMIT
, SEGERA .
Yang di atas dalam prosedur tersimpan:
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 ;
Uji:
set @myNum:= -1;
call getNextSequence('Carburetor',@myNum);
+------------+
| yourSeqNum |
+------------+
| 4 |
+------------+
select @myNum; -- 4
Ubah prosedur tersimpan sesuai kebutuhan Anda, seperti hanya memiliki 1 dari 2 mekanisme untuk mengambil nomor urut (baik parameter OUT atau kumpulan hasil). Dengan kata lain, mudah untuk membuang OUT
konsep parameter.
Jika Anda tidak mematuhi rilis ASAP dari LOCK (yang jelas tidak diperlukan setelah pembaruan), dan melanjutkan untuk melakukan kode yang memakan waktu, sebelum rilis, maka berikut ini dapat terjadi setelah periode waktu habis untuk klien lain yang menunggu urutan nomor:
KESALAHAN 1205 (HY000):Batas waktu tunggu kunci terlampaui; coba mulai ulang transaksi
Semoga ini tidak pernah menjadi masalah.
show variables where variable_name='innodb_lock_wait_timeout';
Halaman Manual MySQL untuk innodb_lock_wait_timeout .
Di sistem saya saat ini memiliki nilai 50 (detik). Menunggu lebih dari satu atau dua detik mungkin tidak tertahankan di sebagian besar situasi.
Yang juga menarik selama TRANSAKSI adalah bagian output dari perintah berikut:
SHOW ENGINE INNODB STATUS;