排他锁的申请前提:没有线程对该结果集中的任何行数据使用排他锁或共享锁,否则申请会阻塞
1、FOR UPDATE 仅适用于InnoDB,且必须在事务区块(BEGIN/COMMIT)中才能生效。
begin
SELECT * FROM x'x'x WHERE xxx FOR UPDATE
commit
2、使用select…for update会把数据给锁住,不过我们需要注意一些锁的级别,MySQL 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;
例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;
例5:(主健和非主建索引)
根据主键、非主键含索引(name)进行查询,并且查询到数据,主键字段产生行锁,name字段产生行锁。
begin;
select * from goods where id = 1 and name='prod11' for update;
commit;
以上就是关于 数据库主键对MySQL锁级别的影响实例
3、除了主键外,使用索引也会影响数据库的锁定级别
举例:表中数据为:
mysql> select * from coupon;
+----+--------+------+
| id | status | name |
+----+--------+------+
| 1 | 1 | A |
| 2 | 2 | B |
+----+--------+------+
例1: (明确指定索引,并且有此数据,row lock)
console1:
mysql> select * from t_goods where status=1 for update;
+----+--------+------+
| id | status | name |
+----+--------+------+
| 1 | 1 | A |
+----+--------+------+
console2:查询status=1的数据时阻塞,超时后返回为空,说明数据被console1锁定了
console2:查询status=2的数据,能正常查询,说明console1只锁住了行,未锁表
例2: (明确指定索引,若查无此数据,无lock)
console1:查询status=3的数据,返回空数据
console2:查询status=3的数据,返回空数据