Innodb 锁定读

如果查询数据,接着在相同的事务中插入或者修改相关数据,常规的select语句不能保护数据不被其他事务修改。其他事务可以更新或者删除刚才查询事务中相同的行。

 

InnoDB支持2种类型的锁定读:

1SELECT ... LOCK IN SHARE MODE设置一个共享S锁在被查询的行上。其他会话能读取这些行,但是不能修改相应行的数据,直到此事务结束。如果其他事务对相应的行进行了DML操作,而未结束事务前,那当前事务中进行SELECT ... LOCK IN SHARE MODE将一直等待,直到另外的事务完成。

2SELECT ... FOR UPDATE设置一个排他X锁在相应的行上。按照索引进行select for update查询时,会锁住相关的索引条目和行数据。同样的,此期间其他事务对相关的行进行更新、SELECT ... LOCK IN SHARE MODE在某些事务隔离级别读数据都将会被堵塞,但一致性读会忽略存在的任何锁,因为老版本的数据不能被锁定,它们通过undo log在内存中构造数据的拷贝。

 

注意:使用锁定读操作的时候,必须开启事务(可以通过START TRANSACTION或者set autocommit=0来开启事务),锁定读相关的锁在事务commit或者rollback时,都会立即释放。如果没有开启事务,则相关的行不会被锁定。

 

用法举例

假如要往子表插入一条记录,插入前首先要确认一下父表有无相关记录,只有在父表有对应记录时插入才能满足应用数据的完整性约束。如果使用一致性非锁定读来检查父表相应的记录,而在往子表插入对应数据的瞬间,其他会话的事务刚好在你查询父表之后插入子表之前删除或者修改了刚才查到的行,这样接下来的插入操作将可能会不能顺利的完成。

 

可以使用LOCK IN SHARE MODE进行锁定读,来避免此潜在的问题。如下:

SELECT * FROM parent WHERE NAME = 'Jones' LOCK IN SHARE MODE;

在父表使用LOCK IN SHARE MODE进行查询到jones,此时你能安全的在子表中插入jones相关的数据。此期间如果有其他会话事务视图DML父表中相应的行将会被阻塞,直到你的完成你的操作后结束锁定读的事务,这样可以保证父表、子表的数据的一致性。

 

另外一个场景,如有两个session需要读取某表A中的一行,在成功读取后在同一事务中更新该行,并在另外的表B中插入刚开始读取到的行。若此时使用SELECT...LOCK IN SHARE MODE则会对读取到A表的记录加S锁,两个session在同时申请X锁进行更新时便发生死锁。另外,由于读取到了A表同一行内容,两个session在向同一表B插入数据时会导致键重复的错误。这种情况下用LOCK IN SHARE MODE不是好的办法,而使用SELECT...FOR UPDATE较合适,在读取的时候阻塞其他事物的读和更新请求。

参考:
http://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/27000195/viewspace-2071786/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/27000195/viewspace-2071786/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值