mysql中select * for update

本文详细介绍了MySQL InnoDB存储引擎中的锁机制,包括Row-Level Lock和Table Lock的区别及应用场景。通过具体的SQL示例,展示了如何根据主键明确与否来决定行级锁还是表级锁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例) ,否则MySQL将会执行Table Lock (将整个资料表单给锁住)。
举个例子:
假设有个表单products ,里面有id跟name二个栏位,id是主键。
例1: (明确指定主键,并且有此笔资料,row lock)
SELECT * FROM products WHERE id='3' FOR UPDATE;
SELECT * FROM products WHERE id='3' and type=1 FOR UPDATE;

例2: (明确指定主键,若查无此笔资料,无lock)
SELECT * FROM products WHERE id='-1' FOR UPDATE;

例2: (无主键,table lock)
SELECT * FROM products WHERE name='Mouse' FOR UPDATE;

例3: (主键不明确,table lock)
SELECT * FROM products WHERE id<>'3' FOR UPDATE;

例4: (主键不明确,table lock)
SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;

注1: FOR UPDATE仅适用于InnoDB,且必须在交易区块(BEGIN/COMMIT)中才能生效。
注2: 要测试锁定的状况,可以利用MySQL的Command Mode ,开二个视窗来做测试。

在MySql 5.0中测试确实是这样的
另外:MyAsim 只支持表级锁,InnerDB支持行级锁
添加了(行级锁/表级锁)锁的数据不能被其它事务再锁定,也不被其它事务修改(修改、删除)
是表级锁时,不管是否查询到记录,都会锁定表

此外,如果A与B都对表id进行查询但查询不到记录,则A与B在查询上不会进行row锁,但A与B都会获取排它锁,此时A再插入一条记录的话则会因为B已经有锁而处于等待中,此时B再插入一条同样的数据则会抛出Deadlock found when trying to get lock; try restarting transaction然后释放锁,此时A就获得了锁而插入成功


上面介绍过SELECT ... FOR UPDATE 的用法,不过锁定(Lock)的数据是判别就得要注意一下了。由于InnoDB 预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL 才会执行Row lock (只锁住被选取的数据) ,否则MySQL 将会执行Table Lock (将整个数据表单给锁住)。

(转载于http://www.cnblogs.com/chenwenbiao/archive/2012/06/06/2537508.html

注意:之前orcale中使用过nowait关键字,以为在mySQL中也可以,但是结果却不是这样的。原因是:目前builtin版本的innodb不支持nowait句法的

### SQL `SELECT ... FOR UPDATE` 用法及语法示例 #### 行锁定机制概述 在关系型数据库中,事务处理通常涉及多个查询和更新操作。为了防止并发事务之间的冲突,某些情况下需要对特定行加锁。`SELECT ... FOR UPDATE` 是一种常用的行级锁定方法,主要用于 InnoDB 存储引擎下的 MySQL 数据库。 当执行带有 `FOR UPDATE` 的查询时,所选中的行会被加上排他锁(exclusive lock),这意味着其他事务无法修改这些行,直到当前事务提交或回滚为止[^3]。 #### 基本语法 以下是 `SELECT ... FOR UPDATE` 的基本语法结构: ```sql SELECT column1, column2, ... FROM table_name WHERE condition FOR UPDATE; ``` - **`column1, column2, ...`**: 查询的目标列。 - **`table_name`**: 被查询的表名称。 - **`condition`**: 过滤条件,用于限定哪些行将被锁定。 - **`FOR UPDATE`**: 明确指示数据库对该查询返回的结果集施加排他锁。 #### 示例代码 假设有一个名为 `products` 的表,其中包含两列:`id` 和 `name`,并且 `id` 列为主键。下面是一些具体的使用场景: ##### 场景一:基于主键锁定单行 如果知道目标行的主键值,则可以直接通过主键进行锁定: ```sql SELECT * FROM products WHERE id = 3 FOR UPDATE; ``` 这条语句会对 `id=3` 的那一行数据加锁,确保在同一事务期间没有其他事务能够对其进行修改[^3]。 ##### 场景二:基于复合条件锁定多行 对于更加复杂的业务逻辑,可能需要根据多个字段组合筛选并锁定若干条记录: ```sql SELECT * FROM products WHERE category = 'Electronics' AND stock < 10 FOR UPDATE; ``` 这里会把所有属于电子产品类别且库存低于十件的商品都标记为已锁定状态[^3]。 #### 注意事项 1. **存储引擎支持** 只有 Innodb 类型的支持行级别锁定功能;MyISAM 不具备该特性因此不适用此类操作[^4]。 2. **显式开启事务环境** 此命令需放置于明确界定好的事务边界之内方能正常运作——即必须位于 BEGIN 至 COMMIT 或 ROLLBACK 执行区间之中[^4]。 3. **潜在死锁风险** 如果两个或者更多进程试图同时获取对方已经持有的资源上的互斥锁就会引发死锁现象。为了避免这种情况发生应该尽量缩短持有时间以及遵循固定的访问顺序模式减少交叉可能性. ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值