很抱歉回答太长,但这需要分多个部分来回答。
1. 关于锁定 InnoDB 表LOCK TABLES
一般来说
Using LOCK TABLES
与 InnoDB 确实有效,并且可以通过连接到同一服务器的 MySQL CLI 的两个实例进行演示(由mysql-1
and mysql-2
)在下面的例子中。由于对客户的影响,通常应该在任何类型的生产环境中避免它,但有时它可能是唯一的选择。
创建一个表并用一些数据填充它:
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
锁定表:
mysql-1> lock tables a write;
Query OK, 0 rows affected (0.00 sec)
尝试插入自mysql-2
,它将挂起等待锁:
mysql-2> insert into a (id) values (4);
现在解锁表mysql-1
:
mysql-1> unlock tables;
Query OK, 0 rows affected (0.00 sec)
最后mysql-2
解锁并返回:
Query OK, 1 row affected (6.30 sec)
2.使用phpMyAdmin进行测试
您使用 phpMyAdmin 的测试方法无效,因为 phpMyAdmin 不会在其 Web 界面的查询之间维持与服务器的持久连接。为了使用任何类型的锁定LOCK TABLES
, START TRANSACTION
等等,您需要在持有锁的同时保持连接。
3. 锁定工作期间需要的所有表
MySQL 锁定表的方式,一旦你使用过LOCK TABLES
要显式锁定任何内容,您将无法访问在此期间未显式锁定的任何其他表LOCK
... UNLOCK
会议。在上面的示例中,您需要使用:
LOCK TABLES my_table WRITE, new_table WRITE, table2 READ;
(我假设table2
子选择中使用的不是拼写错误。)
4. 原子表交换使用RENAME TABLE
另外,我应该注意,使用替换现有表DROP TABLE
其次是RENAME TABLE
将导致该表短暂不存在,这可能会让希望该表存在的客户端感到困惑。一般来说,这样做会更好:
CREATE TABLE t_new (...);
<Populate t_new using some method>
RENAME TABLE t TO t_old, t_new TO t;
DROP TABLE t_old;
这将执行两个表的原子交换。