Php MySQL事务与锁

Php MySQL事务与锁,php,mysql,database,transactions,acid,Php,Mysql,Database,Transactions,Acid,我正在构建一个应用程序,用户可以在其中提交帖子,人们可以回复帖子。当用户发布帖子时,他可以选择哪些用户可以查看帖子 这是posts表: | id | poster-id | title | message | ... | 这是posts可见表。它表示帖子和成员之间的个人关系(一种表示他们可以查看和回复帖子的关系): 这是回复表: | id | posts-id | poster-id | title | message | ... | 现在,当有人添加回复时,我会在事务中运行以下操作: tr

我正在构建一个应用程序,用户可以在其中提交帖子,人们可以回复帖子。当用户发布帖子时,他可以选择哪些用户可以查看帖子

这是posts表:

| id | poster-id | title | message | ... |
这是posts可见表。它表示帖子和成员之间的个人关系(一种表示他们可以查看和回复帖子的关系):

这是回复表:

| id | posts-id | poster-id | title | message | ... |
现在,当有人添加回复时,我会在事务中运行以下操作:

try
{
    $db->beginTransaction();
    // first check if the user is part of the posts-visible group
    $stmt = $db->prepare('SELECT id FROM `posts-visible` WHERE posts-id=:pid AND poster-id=:uid LOCK IN SHARE MODE');
    // ... bind and execute

    if($stmt->rowCount() <= 0) return false; // not in visible group

    $stmt = $db->prepare('INSERT INTO `replies` ... ');
    // binds and execute

    $db->commit();
}
catch(Exception $e)
{
    $db->rollback();
}
试试看
{
$db->beginTransaction();
//首先检查用户是否属于posts可见组
$stmt=$db->prepare('posts visible'中选择id,其中posts id=:pid和poster id=:uid LOCK处于共享模式);
//…绑定并执行
如果($stmt->rowCount()prepare('INSERT INTO'replays`…');
//绑定并执行
$db->commit();
}
捕获(例外$e)
{
$db->rollback();
}
我的问题是:
锁定在共享模式下有必要吗?我设想了一种可能的竞争条件,在这种情况下,原始海报会删除用户对帖子的访问权限,就像用户发布回复一样,在这种情况下,尽管海报不允许用户访问,他仍可以发布回复,因此我将
锁定在共享模式下
,以便其他人能够访问Sessions可以读取但不能修改它。但是,事务是否已经通过在ACID中隔离来保证不会发生同步访问?如果是,什么时候将
锁定在共享模式下合适?为什么将其用于事务

作为第二个问题,我还有一些获取帖子信息的代码(例如帖子内容、标题等)。代码类似,只是在第一次选择后有另一个选择检查访问权限,而不是插入。因为没有写入任何内容,所以交易是必要的吗?这会改变第一次回答的内容吗

最后,还有一个问题。如果我有一个事务在插入行之前检查行是否存在,那么事务是否会阻止另一个事务在行检查和插入之间插入行

谢谢

我的问题是,是否因为事务需要锁

简而言之,是的,你知道

事务所要做的就是在某个跟踪失败时为您提供回滚方法。如果没有锁,则无法知道在两次查询之间是否修改了基础表

请记住,假设您使用的是InnoDB,您的
选择…锁定在共享模式下
只会锁定选定的行,而不会锁定整个表。我强烈建议您阅读本文档,特别是这两种方法之间的差异以及何时使用它们

同样的概念也适用于你的第二个问题,并且解释得很好

最后,它归结为:

锁防止任何其他人干扰任何数据库记录 您正在处理。事务可防止任何“以后”的错误 干扰“以前”你做过的事情。任何人都不能 保证事情最终会顺利进行。但一起做,他们会成功的

在明天的课程中:僵局的喜悦


为什么不创建一个外键呢?我确实在表中的相关列之间有外键约束。但是,帖子可见和回复之间没有关系,所以我不知道这是如何工作的。例如,如果原始海报删除了用户可见的帖子中的条目行,那么回复选项卡就没有约束le.你可以添加一个列,该列引用可见的
帖子。id
从我所读到的来看,锁定/事务不是更适合于此吗?从逻辑上讲,我看不到权限和帖子之间有明确的联系。此外,我希望用户之前创建的帖子能够保留;在权限被撤销后,他就不能再发布了。Doesn不允许多个会话在共享模式下共享锁并且只阻止写入,同时允许更新吗?因此,如果两个事务正在尝试写入,它们是否仍然能够插入,因为实际的插入操作不会影响锁定的行?感谢您的响应!如果上的事务存在以允许在所有或无查询集合中,它如何在ACID中实现隔离?如果是这样,这是否意味着只对选择使用事务没有意义,因为锁的作用是确保没有数据更改,并且事务只有在修改内容时才有用?此外,链接页被破坏:(@untitle我已经更新了链接,出于某种原因,因此在一开始就添加了一个www。是的,在您的上下文中,该事务可能不需要。它更适用于当您希望在出现问题时回滚您所做的更改,例如进行了一些更改,但这些更改要么全部成功,要么没有成功(您回滚)。
try
{
    $db->beginTransaction();
    // first check if the user is part of the posts-visible group
    $stmt = $db->prepare('SELECT id FROM `posts-visible` WHERE posts-id=:pid AND poster-id=:uid LOCK IN SHARE MODE');
    // ... bind and execute

    if($stmt->rowCount() <= 0) return false; // not in visible group

    $stmt = $db->prepare('INSERT INTO `replies` ... ');
    // binds and execute

    $db->commit();
}
catch(Exception $e)
{
    $db->rollback();
}