以前只是听说过数据库锁的概念,什么行锁、表锁。。。。balabala
一直未实践过,今天翻看技术博客时偶见for update,这是一个加锁的操作。索性就看看文档,顺便操作下,把操作过程记录,以备翻阅。
MySQL Locking Read 详细介绍了MySQL中的锁。注意必须使用InnoDB引擎,因为InnoDB支持事务,支持行锁,而MyISAM不支持事务。
言归正传。。。。。
按照官网给的说明,InnoDB支持两种加锁操作,select....for share
和 select....for update
首先来看 select....for share
Sets a shared mode lock on any rows that are read. Other sessions can read the rows, but cannot modify them until your transaction commits. If any of these rows were changed by another transaction that has not yet committed, your query waits until that transaction ends and then uses the latest values.
这是官网给的描述信息,是时候展现真正的技术了····(翻译如下,水平有限勿怪)
对正在读取的数据行设置共享模式锁,其他会话可以读取这些记录,但是在你的当前事务未提交之前不能修改数据。如果这些记录被其他事物修改且尚未提交,则你的查询请求需等待直到该事物结束,然后查询到最新的数据。
实验开始,,,不要眨眼····
表结构与数据
id | name | age | gender |
---|---|---|---|
1 | zh | 23 | male |
2 | zg | 34 | female |
接下来开两个command窗口,我直接在Navicat 中的命令行窗口操作。


可以看出share模式两个事务可以同时读。下面来看看修改的情况


在session-1中做update操作,会等待直到报超时错误。再来试一次update,再等待过程中我们提交session-2的事务。看看结果。。。。

session-2事务commit完,session-1的update操作立刻执行完成。随后查询了表中数据,发现数据已经更改,为什么session-2中的数据还没改呢?因为我session-1中的事务还没有commit,所以session-2看不到我未提交的修改。这与mysql的事务隔离级别有关,有兴趣的可以查询相关资料。
那如果session-1在修改数据,session-2还能获得锁吗?因为session-2刚刚已经commit,session-1 update了数据,此次试验只需在session-2中for share 即可

当session-1执行未提交的update事务时,session-2无法获得相应记录的share锁。

在等待过程中commit session-1的事务。session-2里面获得锁。
接下来看看select...for update
(这段好难翻)
For index records the search encounters, locks the rows and any associated index entries, the same as if you issued an
UPDATE
statement for those rows. Other transactions are blocked from updating those rows, from doingSELECT ... FOR SHARE
, or from reading the data in certain transaction isolation levels. Consistent reads ignore any locks set on the records that exist in the read view. (Old versions of a record cannot be locked; they are reconstructed by applying undo logs on an in-memory copy of the record.)
对于搜索遇到的索引记录,锁定行和任何关联的索引条目,就像要在这些行执行UPDATE语句一样。阻止其他事务的更新这些行、执行select...for share或在某些事务隔离级别下读取数据的操作。一致性读取(Consistent Read)将忽略在读视图中存在的记录上设置的任何锁。 (旧版本的记录无法锁定;它们是通过在记录的内存副本上应用撤消日志来重建)

session-1使用for update获得行锁,session-2中for update与for share都会等待超时。

session-2的update操作同样会阻塞等待。
网友评论