欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

InnoDB中的select..forupdate语句

程序员文章站 2022-04-12 21:20:41
InnoDB中的select .. for update语句: 1)select .. for update语句仅适用于InnoDB 2)select .. for updat...
InnoDB中的select .. for update语句:

	1)select .. for update语句仅适用于InnoDB
	2)select .. for update语句必须在事务中才能生效。
	3)在执行事务中的select .. for update语句时,MySQL会对查询结果集中的每行数据都添加排他锁(行锁、表锁),其它线程对锁定行的 更新、删除、select .. for update查询 这3种操作都会被阻塞,一般的select语句不会被阻塞。
	4)查看自动提交是否开启(1表示开启,0表示关闭,默认开启): select @@autocommit

排它锁的选择:

	若where条件中明确指定了主键,且该行数据存在,则只锁定该行,故排它锁为行锁(row lock)。
	若where条件中明确指定了主键,但是该行数据不存在,则不会加锁。
	
	若where条件中明确指定了索引,且该行数据存在,则只锁定该行,故排它锁为行锁(row lock)。
	若where条件中明确指定了索引,但是该行数据不存在,则不会加锁。
	
	若where条件中未明确指定主键或索引,则会锁定全表,故排它锁为表锁(table lock)。
	注:未明确指定 即 未指定(主键/索引) 或 指定的是(主键/索引)的范围
	

eg:
	# 只锁定message_id为1的行
	set autocommit=0;
	begin;
	select * from t_message where message_id=1 for update; # message_id为主键
	commit;

	# 锁定全表
	set autocommit=0;
	begin;
	select * from t_message where message_id>1 for update; # message_id为主键
	commit;
	
	# 锁定全表
	set autocommit=0;
	begin;
	select * from t_message where type='good' for update; # good非索引列
	commit;


	其它线程因为等待(排它锁)超时而报错:
	update t_message set title='asdf' where message_id=1;
	[Err] 1205 - Lock wait timeout exceeded; try restarting transaction