com*_*ral 3 mysql innodb locking
我想暂时锁定一个表,以防止其他并发进程对其进行更改.原因是这个表将被复制到临时表,更改,然后被复制回来(实际上删除了原始表并重命名了新表).然后在完成所有这些之后,我想解锁表格并希望在锁定恢复期间尝试任何尝试.
我还需要能够从已锁定的表中读取以构建新表.
这是我尝试过的,但它似乎不起作用.
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, DB_PORT);
$mysqli->autocommit(false)
// create a table to hold parts to keep
$q1 = "CREATE TABLE new_table LIKE my_table;";
$res1 = $mysqli ->query($q1);
// Lock table to avoid concurrent update issues
$q2 = "LOCK TABLE my_table WRITE;";
$res2 = $mysqli ->query($q2);
// Insert data to keep into new table
$q3 = "INSERT INTO new_table SELECT * FROM my_table WHERE some_id IN (SELECT ID FROM table2)";
$res3 = $mysqli ->query($q3);
// drop original table
$q4 = "DROP TABLE my_table;";
$res4 = $mysqli ->query($q4);
// rename new table
$q5 = "RENAME TABLE new_table TO my_table;";
$res5 = $mysqli ->query($q5);
$mysqli ->commit(); // commit changes and re-enable autocommit
$q = "UNLOCK TABLES;";
$res = $mysqli ->query($q);
Run Code Online (Sandbox Code Playgroud)
为了测试,使用PHPmyadmin,我发布了"SET AUTOCOMMIT = 0; LOCK TABLE my_table WRITE;" 查询,然后尝试从my_table删除一些东西,我能够这样做.我想阻止这个.此外,在发出lock语句之后,该过程的其余部分将失败,并且不会更改任何内容.
jer*_*ole 10
对不起,答案很长,但需要分多个部分来解答.
1. LOCK TABLES一般情况下锁定InnoDB表
LOCK TABLES与InnoDB一起使用实际上可以工作,并且可以通过连接到同一服务器的两个MySQL CLI实例(用mysql-1和表示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
Run Code Online (Sandbox Code Playgroud)
锁定桌子:
mysql-1> lock tables a write;
Query OK, 0 rows affected (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
尝试插入mysql-2,将挂起等待锁:
mysql-2> insert into a (id) values (4);
Run Code Online (Sandbox Code Playgroud)
现在解锁表mysql-1:
mysql-1> unlock tables;
Query OK, 0 rows affected (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
最后mysql-2取消阻止并返回:
Query OK, 1 row affected (6.30 sec)
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
(我假设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;
Run Code Online (Sandbox Code Playgroud)
这将执行两个表的原子交换.