Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment puis-je verrouiller une table InnoDB pour empêcher les mises à jour pendant la copie de cette table ?

Désolé pour la longue réponse, mais il faudra y répondre en plusieurs parties.

1. Sur le verrouillage des tables InnoDB avec LOCK TABLES en général

Utilisation de LOCK TABLES avec InnoDB fonctionne en fait, et peut être démontré avec deux instances de MySQL CLI connectées au même serveur (noté par mysql-1 et mysql-2 ) dans l'exemple ci-dessous. Cela devrait généralement être évité dans tout type de contexte de production en raison de l'impact sur les clients, mais parfois cela peut être la seule option.

Créez un tableau et remplissez-le avec des données :

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

Verrouiller la table :

mysql-1> lock tables a write;
Query OK, 0 rows affected (0.00 sec)

Essayez d'insérer depuis mysql-2 , qui se bloquera en attente sur la serrure :

mysql-2> insert into a (id) values (4);

Déverrouillez maintenant la table depuis mysql-1 :

mysql-1> unlock tables;
Query OK, 0 rows affected (0.00 sec)

Et enfin mysql-2 débloque et renvoie :

Query OK, 1 row affected (6.30 sec)

2. Utilisation de phpMyAdmin pour les tests

Votre méthode de test utilisant phpMyAdmin n'est pas valide car phpMyAdmin ne maintient pas une connexion persistante au serveur entre les requêtes de son interface Web. Afin d'utiliser n'importe quel type de verrouillage LOCK TABLES , START TRANSACTION , etc., vous devez maintenir une connexion pendant que les verrous sont maintenus.

3. Verrouillage de toutes les tables nécessaires pendant le travail

La façon dont MySQL verrouille les tables, une fois que vous avez utilisé LOCK TABLES pour verrouiller explicitement quoi que ce soit, vous ne pourrez accéder à aucune autre table qui n'a pas été verrouillée explicitement pendant le LOCK ... UNLOCK session. Dans votre exemple ci-dessus, vous devez utiliser :

LOCK TABLES my_table WRITE, new_table WRITE, table2 READ;

(Je suppose table2 utilisé dans la sous-sélection n'était pas une faute de frappe.)

4. Échange de table atomique à l'aide de RENAME TABLE

De plus, je dois noter que le remplacement de la table existante à l'aide de DROP TABLE suivi de RENAME TABLE provoquera un bref moment où la table n'existe pas, et cela peut dérouter les clients qui s'attendent à ce qu'elle existe. Il est généralement préférable de faire :

CREATE TABLE t_new (...);
<Populate t_new using some method>
RENAME TABLE t TO t_old, t_new TO t;
DROP TABLE t_old;

Cela effectuera un échange atomique des deux tables.