Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

mysql - membuat mekanisme yang mirip dengan urutan Oracle

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;



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Praktik Terbaik untuk Membuat Indeks di Tabel MySQL Anda – Rolling Index Builds

  2. WEEK() Contoh – MySQL

  3. SQL Memilih dari dua Tabel dengan gabungan dan batas dalam

  4. Perbaiki "ERROR 3942 (HY000):Setiap baris klausa VALUES harus memiliki setidaknya satu kolom" saat menggunakan Pernyataan VALUES di MySQL

  5. Ketersediaan Tinggi dengan Anggaran Sedikit - Menyebarkan Cluster Galera MySQL Dua Node Minimal