回答

收藏

使用MySQL的FOR UPDATE锁定时,究竟锁定了什么?

技术问答 技术问答 105 人阅读 | 0 人回复 | 2023-09-13

这不是完整/正确的MySQL查询伪代码:" h+ m, X. G3 t5 P
Select *
) f9 x" d0 g1 `5 k, F from Notifications as n
9 ^8 k. N2 R; k7 P where n.date > (CurrentDate-10 days)' w3 R9 v% Q! _0 `
limit by 1
; i+ k4 V' h3 g/ I. S FOR UPDATE/ @+ s' @! I) u  f3 D
http://dev.mysql.com/doc/refman/5.0/en/select.html指出:如果将FOR; C) h. P; N6 u( M. C
UPDATE与使用页面或行锁的存储引擎一起使用,则查询所检查的行将被写锁,直到当前交易结束
( G) i/ ^7 ~* D- i+ a9 ^' J" H是这里只有被MySQL锁定返回的一条记录还是必须扫描以查找单个记录的所有记录?
7 i/ Q" J, i# m- d  B                : [7 N  o4 z" E
解决方案:
$ {1 U9 E3 r  R" B8 ?               
/ H. M7 S" D) t- l
5 K6 u2 [% m' @& l& o  n" \" o/ j; K9 X( H: \- ]8 k1 N  ]0 B
                我们为什么不尝试一下呢?
2 }+ Q! P+ X6 d1 @2 P设置数据库# {  d+ A- o2 ~' W) t
CREATE DATABASE so1;6 a! y2 K! B' _" T
USE so1;6 e( X( G& D0 h! V; [* ?
CREATE TABLE notification (`id` BIGINT(20), `date` DATE, `text` TEXT) ENGINE=InnoDB;
" M3 f& D, r$ C. [INSERT INTO notification(id, `date`, `text`) values (1, '2011-05-01', 'Notification 1');
0 }/ Z! k7 ~& b1 JINSERT INTO notification(id, `date`, `text`) values (2, '2011-05-02', 'Notification 2');$ Y4 u) B% ]% K, k! y. A
INSERT INTO notification(id, `date`, `text`) values (3, '2011-05-03', 'Notification 3');+ S, t4 i) C2 O9 t* L) ~/ a
INSERT INTO notification(id, `date`, `text`) values (4, '2011-05-04', 'Notification 4');
3 \, B! D9 ^6 w! z3 MINSERT INTO notification(id, `date`, `text`) values (5, '2011-05-05', 'Notification 5');
# g* U1 F& m  T! I: b现在,启动两个数据库连接3 `: r& i5 X( X- Z$ S
连接1: ~, o, b/ e2 m4 L
BEGIN;
* S4 A# J- r! ZSELECT * FROM notification WHERE `date` >= '2011-05-03' FOR UPDATE;
/ a. q# X, f4 j8 O9 g连接2; l% _' `/ M; f6 O& Y; {  y
BEGIN;# w( _, N" }; R3 o
如果MySQL锁定所有行,则以下语句将阻塞。如果仅锁定返回的行,则不应阻塞。3 J+ u% [; l$ z
SELECT * FROM notification WHERE `date` = '2011-05-02' FOR UPDATE;
# ^! i8 B- J" T6 E! [2 Z! U确实的确会阻止。
( a0 E4 D. ?' n7 Q! u有趣的是,我们也无法添加将要读取的记录,即
+ b8 I# C, S( g' I& W# UINSERT INTO notification(id, `date`, `text`) values (6, '2011-05-06', 'Notification 6');
; Q: T# o" m" v7 p) r1 T块呢!
% _# r0 E3 I& p5 ]) k$ w7 N( I我现在不能确定MySQL是否只是在锁定一定百分比的行时继续执行并锁定整个表,或者在确保SELECT ... FORUPDATE查询结果永远不会被其他事务更改的情况下真正明智的做法是(用INSERT,UPDATE或DELETE),而锁被保持。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则