Red*_*148 3 sql primary-key sql-delete
我想删除数据库中的一行,我有 2 个选项;一是用普通列删除行,二是主键?
我知道主键更好,但为什么呢?
在 MySql 上,在使用非主键列删除/更新行时,您可能会在多用户环境中遇到奇怪的锁定行为。
这是一个示例 - 两个会话试图删除行(禁用自动提交)。
C:\mysql\bin>mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.5.29-log MySQL Community Server (GPL)
Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
mysql> create table test(
-> id int primary key,
-> val int
-> );
Query OK, 0 rows affected (0.02 sec)
......
mysql> select * from test;
+----+------+
| id | val |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
+----+------+
6 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
现在在会话 1 中,我们将使用主键删除第 5 行
mysql> delete from test where id = 5;
Query OK, 1 row affected (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
然后在会话 2 中,我们也使用 PK 删除第 2 行
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from test where id = 2;
Query OK, 1 row affected (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
一切看起来都不错 - 第 5 行被会话 1 删除,第 2 行在会话 2 中删除
现在看看当我们尝试使用非主键删除行时会发生什么:
会话 1
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from test where val = 5;
Query OK, 1 row affected (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
和会话 2
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from test where val = 2;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql>
Run Code Online (Sandbox Code Playgroud)
会话 2 中的删除命令“挂起”,大约一分钟后它抛出一个错误:锁定等待超时
让我们尝试删除其他行:
mysql> delete from test where val = 4;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> delete from test where val = 6;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql>
Run Code Online (Sandbox Code Playgroud)
会话 1 只删除第 5 行,从逻辑上讲,锁应该只放在被删除的第 5 条记录上,但正如你在这些例子中看到的,当不使用主键时,MySql 将锁放在整个表的所有行上. 因此,仅使用主键(至少在 MySql 上)删除行会更安全。