当前位置:   article > 正文

MySQL-数据操作类型的角度理解 S锁 & X锁

MySQL-数据操作类型的角度理解 S锁 & X锁

1、S锁和S锁互相兼容

在这里插入图片描述

2、S锁和X锁互斥

在这里插入图片描述

3、X锁和X锁也互斥

在这里插入图片描述

4、X锁和S锁也互斥

在这里插入图片描述

5、select * from account for update;

SELECT * FROM account FOR UPDATE; 是一个SQL语句,通常用于数据库管理系统(如Oracle, PostgreSQL, MySQL的InnoDB存储引擎等)中,用于锁定所选的行以供后续更新。

以下是这条语句的详细解释:

  1. SELECT * FROM account

    • 这部分是一个标准的SELECT语句,用于从account表中检索所有列和所有行。
  2. FOR UPDATE

    • 这是一个锁定子句,用于锁定所选的行。一旦这些行被锁定,其他事务就不能修改或删除它们,直到当前事务完成(提交或回滚)。
    • 这种锁定机制通常用于确保数据的一致性,特别是在涉及多个步骤的复杂事务中。
    • 注意:不同的数据库管理系统对FOR UPDATE的锁定行为和范围可能有不同的实现。例如,在某些系统中,它可能只锁定所查询的行(行级锁定),而在其他系统中,它可能锁定整个表(表级锁定)。

使用场景

假设你有一个在线银行系统,用户A正在尝试从他的账户中转账到用户B的账户。为了确保转账过程中账户余额的一致性,你可能需要执行以下步骤:

  1. 使用SELECT * FROM account WHERE id = A's_account_id FOR UPDATE;锁定用户A的账户。
  2. 检查用户A的账户余额是否足够进行转账。
  3. 如果余额足够,从用户A的账户中扣除相应金额,并增加用户B的账户余额。
  4. 提交事务,释放锁。

通过这种方式,你可以确保在用户A的账户被检查和更新之间,没有其他事务修改它,从而避免了潜在的数据不一致问题。

6、select * from account for update nowait;

SELECT * FROM account FOR UPDATE NOWAIT; 是一条SQL语句,通常用于数据库中的事务处理,特别是在需要锁定某些行以确保数据一致性的情况下。下面我会详细解释这条语句的每个部分:

  1. SELECT * FROM account

    • 这部分是一个标准的SELECT查询,它从account表中选择所有列(因为使用了*)。
  2. FOR UPDATE

    • FOR UPDATE是一个锁定子句,用于在事务中锁定选定的行。这意味着一旦某个事务执行了这个查询并锁定了某些行,其他尝试修改这些行的事务将被阻塞,直到第一个事务提交或回滚。
    • 这种锁定通常用于确保数据的完整性和一致性,尤其是在并发操作的环境中。
  3. NOWAIT

    • NOWAIT是一个与FOR UPDATE一起使用的选项。当指定了NOWAIT时,如果请求的行当前已被其他事务锁定,那么查询将立即返回一个错误,而不是等待其他事务释放锁。
    • 这对于不希望因为等待锁而被阻塞的应用程序来说是非常有用的。通过立即得到一个错误,应用程序可以决定如何响应(例如,重试、报告错误给用户等)。

示例场景

假设你有一个银行应用程序,两个用户(A和B)同时尝试从同一个账户(假设账户ID为123)中取款。为了避免出现“超支”的情况(即两个用户都成功取款,但账户余额不足以支付两次取款),数据库需要确保一次只有一个用户能够访问和修改该账户。

  • 用户A开始一个事务,并执行SELECT * FROM account WHERE id = 123 FOR UPDATE NOWAIT;。假设此时账户余额足够支付用户A的取款请求。
  • 在用户A的事务完成之前(即提交或回滚之前),用户B也尝试执行相同的查询。
  • 因为用户A的事务已经锁定了账户ID为123的行,并且由于使用了NOWAIT选项,所以用户B的查询将立即返回一个错误,而不是等待用户A的事务完成。
  • 用户B的应用程序可以捕获这个错误,并决定如何响应(例如,告诉用户B稍后再试)。

这样,通过使用FOR UPDATE NOWAIT,你可以确保数据的一致性和完整性,同时减少因为等待锁而导致的延迟和可能的死锁情况。
在这里插入图片描述

7、select * from account for update skip locked;

SELECT * FROM account FOR UPDATE SKIP LOCKED; 这条SQL语句在支持该语法的数据库中(如Oracle、PostgreSQL等)用于在尝试锁定表或表中的行时跳过已经被其他事务锁定的行。这允许查询快速返回一个结果集,其中只包含当前事务可以立即锁定的行,而忽略那些已被其他事务锁定的行。

这条语句通常用于高并发的数据库环境中,特别是当多个事务需要同时访问并更新相同的资源时。通过使用SKIP LOCKED选项,可以避免一个事务长时间等待另一个事务释放锁,从而提高整个系统的吞吐量和响应速度。

以下是这条语句的一些关键点:

  1. SELECT * FROM account:选择account表中的所有列。
  2. FOR UPDATE:指示数据库锁定所选的行,以便在后续的事务中更新它们。
  3. SKIP LOCKED:如果所选的行已被其他事务锁定,则跳过这些行并继续选择其他未被锁定的行。

示例场景

假设你有一个在线购物网站,并且多个用户同时尝试购买同一件商品(库存有限)。为了确保商品不会被超卖,每次购买时都需要锁定相应的库存记录并进行更新。

  • 用户A开始一个事务,并尝试锁定库存中数量大于0的商品。假设商品ID为123,当前库存为1。
  • 在用户A的事务完成之前(即提交或回滚之前),用户B也尝试购买同一件商品。
  • 由于用户A已经锁定了商品ID为123的记录,所以用户B的查询(使用FOR UPDATE SKIP LOCKED)将跳过已被锁定的记录,并继续查找其他未被锁定的商品。
  • 如果此时没有其他商品可购买,用户B的事务将不会等待用户A的事务完成,而是立即返回一个空的结果集或相应的错误消息。

通过使用FOR UPDATE SKIP LOCKED,你可以提高并发性能,避免不必要的等待,并为用户提供更快的响应速度。然而,请注意,这种机制并不能完全解决并发冲突,特别是在高并发的环境中。你可能还需要结合其他技术(如乐观锁、重试机制等)来确保数据的一致性和完整性。
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/779472
推荐阅读
相关标签
  

闽ICP备14008679号