Ursäkta det långa svaret, men detta måste besvaras i flera delar.
1. Om att låsa InnoDB-tabeller med LOCK TABLES
i allmänhet
Använder LOCK TABLES
med InnoDB fungerar faktiskt, och kan demonstreras med två instanser av MySQL CLI ansluten till samma server (betecknad med mysql-1
och mysql-2
) i exemplet nedan. Det bör i allmänhet undvikas i alla slags produktionssammanhang på grund av påverkan på kunderna, men ibland kan det vara det enda alternativet.
Skapa en tabell och fyll i den med lite 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)
Försök att infoga från mysql-2
, som kommer att hänga och vänta på låset:
mysql-2> insert into a (id) values (4);
Lås nu upp tabellen från mysql-1
:
mysql-1> unlock tables;
Query OK, 0 rows affected (0.00 sec)
Och slutligen mysql-2
låser upp och returnerar:
Query OK, 1 row affected (6.30 sec)
2. Använda phpMyAdmin för testning
Din testmetod som använder phpMyAdmin är ogiltig eftersom phpMyAdmin inte upprätthåller en beständig anslutning till servern mellan frågor från dess webbgränssnitt. För att använda någon form av låsning LOCK TABLES
, START TRANSACTION
, etc., måste du upprätthålla en anslutning medan låsen hålls.
3. Låsning av alla bord som behövs under arbetet
Sättet som MySQL låser tabeller när du har använt LOCK TABLES
för att explicit låsa någonting kommer du inte att kunna komma åt några andra tabeller som inte var explicit låsta under LOCK
... UNLOCK
session. I ditt exempel ovan måste du använda:
LOCK TABLES my_table WRITE, new_table WRITE, table2 READ;
(Jag antar table2
som användes i undervalet var inte ett stavfel.)
4. Byte av atomtabell med RENAME TABLE
Dessutom bör jag notera att ersätta den befintliga tabellen med DROP TABLE
följt av RENAME TABLE
kommer att orsaka ett kort ögonblick där tabellen inte existerar, och detta kan förvirra klienter som förväntar sig att det finns. Det är i allmänhet mycket bättre att göra:
CREATE TABLE t_new (...);
<Populate t_new using some method>
RENAME TABLE t TO t_old, t_new TO t;
DROP TABLE t_old;
Detta kommer att utföra ett atomärt byte av de två tabellerna.