Beklager det lange svar, men dette skal besvares i flere dele.
1. Om låsning af InnoDB-tabeller med LOCK TABLES
generelt
Brug af LOCK TABLES
med InnoDB fungerer faktisk og kan demonstreres med to forekomster af MySQL CLI forbundet til den samme server (betegnet med mysql-1
og mysql-2
) i nedenstående eksempel. Det bør generelt undgås i enhver form for produktionssammenhæng på grund af indvirkningen på kunderne, men nogle gange kan det være den eneste mulighed.
Opret en tabel og udfyld den med nogle data:
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
Lås bordet:
mysql-1> lock tables a write;
Query OK, 0 rows affected (0.00 sec)
Prøv at indsætte fra mysql-2
, som vil hænge og vente på låsen:
mysql-2> insert into a (id) values (4);
Lås nu tabellen op fra mysql-1
:
mysql-1> unlock tables;
Query OK, 0 rows affected (0.00 sec)
Og endelig mysql-2
ophæver blokering og returnerer:
Query OK, 1 row affected (6.30 sec)
2. Brug af phpMyAdmin til test
Din testmetode ved hjælp af phpMyAdmin er ugyldig, fordi phpMyAdmin ikke opretholder en vedvarende forbindelse til serveren mellem forespørgsler fra dens webgrænseflade. For at bruge enhver form for låsning LOCK TABLES
, START TRANSACTION
osv., skal du bevare en forbindelse, mens låsene holdes.
3. Låsning af alle nødvendige borde under arbejdet
Den måde MySQL låser tabeller på, når du har brugt LOCK TABLES
for eksplicit at låse noget, vil du ikke være i stand til at få adgang til andre tabeller, der ikke var låst eksplicit under LOCK
... UNLOCK
session. I dit eksempel ovenfor skal du bruge:
LOCK TABLES my_table WRITE, new_table WRITE, table2 READ;
(Jeg antager table2
brugt i undervalget var ikke en tastefejl.)
4. Atomisk tabel swap ved hjælp af RENAME TABLE
Derudover skal jeg bemærke, at udskiftning af den eksisterende tabel ved hjælp af DROP TABLE
efterfulgt af RENAME TABLE
vil forårsage et kort øjeblik, hvor tabellen ikke eksisterer, og dette kan forvirre klienter, der forventer, at den eksisterer. Det er generelt meget bedre at gøre:
CREATE TABLE t_new (...);
<Populate t_new using some method>
RENAME TABLE t TO t_old, t_new TO t;
DROP TABLE t_old;
Dette vil udføre et atomudskiftning af de to tabeller.