如果你查询数据然后插入或者更新相关的记录在同一个事务里,

常规的SELECT 语句没有给足够的保护。其他的事务可以更新或者删除相同的记录 你查询的记录,

InnoDB 支持2种类型的lockding reads 提供额外的保护:

1.SELECT … LOCK IN SHARE MODE 设置一个共享的模式锁在任何你读取的记录,

其他会话可以读取行, 但是不能修改 直到你的事务提交。

如果任何的记录别另外的事务修改 没有被提交,你的查询等待直到事务结束然后使用最新的值

2.对于搜索遇到的index records,, SELECT … FOR UPDATE 锁住记录和任何相关的index entries,

类似的如果你执行一个UPDATE语句对于那些记录。

其他的事务是被堵塞的 当更新那些记录的时候,doing SELECT … LOCK IN SHARE MODE,

或者 从读取数据在某个事务隔离级别。

一致读忽略任何锁设置在记录上 存在在读视图里。(老的版本的记录不能被锁定,

他们是通过应用undo logs来重构 在一个记录的内存拷贝)

那些子句是有用的 当处理树形结构或者图形机构化数据,

无论是单个表或者分散到多个表。你遍历或者从树的branched 从一个地方到另外一个,

所有的锁通过 LOCK IN SHARE MODE和 FOR UPDATE 查询是释放的当事务是提交或者回滚。

注意:

锁住的记录用于Update 使用 SELECT FOR UPDATE 只有应用当autocommit 是关闭的(

或者开始事务使用TRANSACTION 或者通过设置 autocommit to 0.如果 autocommit 是启用的,

匹配的记录不会被锁定)

使用例子:

假设你需要插入一条心的记录到一个子表,确保子记录有一个父记录在父表里。

你的应用代码可以确认引用的完整性通过这些操作顺序。

首选,使用一个一致性读来查询父表和校验父表中的记录存在,

你可以安全的插入子记录到子表吗? 不是的,因为 一些其他的会话可能删除父表的记录在你SELECT 和INSERT那会。

为了避免这个潜在的错误,执行SELECT 使用LOCK IN SHARE MODE:

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

在 LOCK IN SHARE MODE 查询返回 parent表的 ‘Jones’, 你可以 安全的增加子表记录到CHILD 表

然后提交事务。 任何事务尝试读取或者写相应的记录到parent表 等待直到你完成,

另外一个例子, 考虑一个整型的counter列在表CHILD_CODES,

用于分配一个唯一的标识对于每个child 被增加到表CHILD.

不要使用任何一致读或者一个共享模式的去来读当前的counter的值,

因为两个数据库的用户可以看到counter相同的值,一个重复-key的错误如果两个事物尝试

增加相同的记录