使用MyISAM意外双插入

时间:2015-04-23 08:49:35

标签: php mysql mysqli innodb

我为我的网站中的产品提供了like表格。

问题是,我使用这个表:

CREATE TABLE IF NOT EXISTS `likes` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `user` varchar(40) NOT NULL,
  `post` int(11) UNSIGNED NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ;

喜欢的用户,帖子是产品ID。

like按钮向这个php发送ajax请求:

session_start();
$user = $_SESSION["user"];
$pinsid=$_POST['id'];

$stmt = $mysqli_link->prepare("SELECT * FROM likes WHERE post=? AND user=?");
$stmt->bind_param('is', $pinsid, $user);
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
$chknum = $result->num_rows;

if($chknum==0){
    $stmt = $mysqli_link->prepare("INSERT INTO likes (user, post) VALUES (?,?)");
    $stmt->bind_param('si', $user, $pinsid);
    $stmt->execute();
    $stmt->close();
    $response = 'success';
 }

echo json_encode($response);

我的问题是,我有来自同一个人的双重插入。例如:

1 josh 5
2 josh 5

但只有当MySQL引擎设置为InnoDB时才会发生,如果我将其更改为MyISAM,我只有1个插入。

发生了什么事?我该怎么做才能让它正常工作?

2 个答案:

答案 0 :(得分:1)

这样做的一种方法是为用户设置一个唯一的密钥,并在like表中发布(参见https://dev.mysql.com/doc/refman/5.0/en/constraint-primary-key.html)。

如果存在,数据库将确保没有重复的用户和帖子。但是,对于已经在表中的数据,如果已经存在重复,则可能会出现问题

答案 1 :(得分:1)

  

但只有当MySQL引擎设置为InnoDB时才会发生,如果我将其更改为MyISAM,我只有1个插入。   怎么了?我该怎么做才能让它正常工作?

MyISAM引擎使用表级锁定,这意味着如果某个操作正在表上执行,则所有其他操作都会等待执行直到该操作完成。

InnoDb是事务性的并且使用行级锁定,因为您没有使用事务,所以没有锁定。

正如评论和答案中所提到的,最简单的解决方案是在用户和帖子上创建一个唯一约束,在这种情况下,您可以将两者都用作主键,因为自动增量列没有附加值。

创建唯一约束:

ALTER TABLE likes ADD UNIQUE KEY uk_user_post (user,post);

关于你的问题:

  

但它会减慢我的插入速度吗?

如果我们只谈论表中的插入操作,是的,它确实会减慢,因为在插入,更新或删除操作之后必须重建每个索引。它减慢了多少取决于索引的大小和表中的行数。

但是在当前的表结构中,userpost上根本没有索引,并且在您的应用程序中,您执行select并在两个列上执行查找,这将生成一个完整的表扫描。

使用唯一索引(user,post),您可以跳过选择,因为当违反唯一约束时,您将收到SQL错误。

此外,userpost是外键,因此无论如何都要编制索引。

唯一索引(user,post)涵盖user FK,因此您还需要post分离的索引

相关问题