关于 select for update

作用

for update不仅可以锁行,也可以锁表。
仅适用于InnoDB。通常使用该语句对数据进行手工加锁,避免其他线程对该数据进行修改,造成数据不一致性。

 

锁的范围

行锁:明确指定Id,且数据存在

select * from customer where id = 1124 for UPDATE

表锁:未指定Id或Id不明确

-- 未指定Id列
SELECT * from customer where name = 1112 for update

-- Id不明确
SELECT * from customer where id <> 11 for update

以上可通过变量innodb_row_lock进行观察

 

模拟表锁

线程A,未指定Id列,会造成表锁

线程B,对id=1的数据加锁,此时因为线程A表锁了,需要等待线程A释放才可以加锁

 

锁的场景
for update 悲观锁,当前线程在处理时,希望别的线程对当前数据无法进行操作。

线程A

BEGIN;

-- 将ID=1的数据锁住
SELECT * FROM work_order WHERE id = 1 FOR UPDATE;

-- 模拟事物未提交
-- COMMIT;

执行结果,对id=1 的数据进行加锁,但是未提交事物,此时别的线程只可读却无法更改

线程B

BEGIN;

-- 查询出id=1的数据
SELECT * FROM work_order WHERE id = 1 ;

-- 修改id=1的状态为V
UPDATE work_order set `status` = 'V' WHERE id = 1 ;

COMMIT;

执行结果,可以查询出id=1的数据,修改时会等待线程A释放锁,否则会进行等待

 

innodb_row_lock 

Innodb_row_lock_current_waits : 当前等待的锁的数量

Innodb_row_lock_time:锁的总时长

Innodb_row_lock_time_avg:每次等待锁花时间的平均数

Innodb_row_lock_time_max:最大的一次等待锁花的时间

Innodb_row_lock_waits:一共等待锁的次数

 

 

posted @ 2020-11-18 11:32  swayer  阅读(215)  评论(0编辑  收藏  举报