数据库中用于删除行的主键或常规字段?

Red*_*148 3 sql primary-key sql-delete

我想删除数据库中的一行,我有 2 个选项;一是用普通列删除行,二是主键?

我知道主键更好,但为什么呢?

kro*_*lko 5

在 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 上)删除行会更安全。