Omlouvám se za dlouhou odpověď, ale bude potřeba odpovědět v několika částech.
1. Na zamykání tabulek InnoDB pomocí LOCK TABLES
obecně
Pomocí LOCK TABLES
s InnoDB ve skutečnosti funguje a lze to demonstrovat na dvou instancích MySQL CLI připojených ke stejnému serveru (označeno mysql-1
a mysql-2
) v níže uvedeném příkladu. Obecně je třeba se mu vyhnout v jakémkoli produkčním kontextu kvůli dopadu na klienty, ale někdy to může být jediná možnost.
Vytvořte tabulku a naplňte ji daty:
mysql-1> create table a (id int not null primary key) engine=innodb;
Query OK, 0 rows affected (0.02 sec)
mysql-1> insert into a (id) values (1), (2), (3);
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
Zamkněte stůl:
mysql-1> lock tables a write;
Query OK, 0 rows affected (0.00 sec)
Zkuste vložit z mysql-2
, který bude viset čekat na zámku:
mysql-2> insert into a (id) values (4);
Nyní odemkněte tabulku z mysql-1
:
mysql-1> unlock tables;
Query OK, 0 rows affected (0.00 sec)
A nakonec mysql-2
odblokuje a vrátí:
Query OK, 1 row affected (6.30 sec)
2. Použití phpMyAdmin pro testování
Vaše testovací metoda pomocí phpMyAdmin je neplatná, protože phpMyAdmin neudržuje trvalé spojení se serverem mezi dotazy ze svého webového rozhraní. Chcete-li použít jakýkoli druh zamykání, LOCK TABLES
, START TRANSACTION
, atd., musíte udržovat spojení, dokud jsou zámky drženy.
3. Uzamčení všech stolů potřebných při práci
Způsob, jakým MySQL zamyká tabulky, jakmile použijete LOCK TABLES
chcete-li cokoli explicitně uzamknout, nebudete mít přístup k žádným dalším tabulkám, které nebyly explicitně uzamčeny během LOCK
... UNLOCK
zasedání. Ve výše uvedeném příkladu musíte použít:
LOCK TABLES my_table WRITE, new_table WRITE, table2 READ;
(Předpokládám table2
použitý v dílčím výběru nebyl překlep.)
4. Atomic table swap pomocí RENAME TABLE
Dále bych měl poznamenat, že nahrazení stávající tabulky pomocí DROP TABLE
následuje RENAME TABLE
způsobí krátký okamžik, kdy tabulka neexistuje, a to může zmást klienty, kteří její existenci očekávají. Obecně je mnohem lepší udělat:
CREATE TABLE t_new (...);
<Populate t_new using some method>
RENAME TABLE t TO t_old, t_new TO t;
DROP TABLE t_old;
Tím dojde k atomickému prohození dvou tabulek.