14.5.2.4 Locking Reads 锁定读:
如果你查询数据然后插入或者修改相关数据在相同的事务里, 常规的SELECT 语句不能给予足够的保护。
其他事务可以修改或者删除你刚查询相同的记录,InnoDB 支持2个锁定读的类型提供额外的安全:
/*******************
测试MYSQL RR 的重复读:
CREATE TABLE `t3` (
`sn` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
`phoneNo` int(11) DEFAULT NULL,
PRIMARY KEY (`sn`));
mysql> show create table t3;
+-------
+------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------+
| Table | Create Table
|
+-------
+------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------+
| t3 | CREATE TABLE `t3` (
`sn` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
`phoneNo` int(11) DEFAULT NULL,
PRIMARY KEY (`sn`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------
+------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------+
1 row in set (0.00 sec)
Session 1:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t3;
+----+---------+
| sn | phoneNo |
+----+---------+
| 1 | 11 |
| 2 | 22 |
+----+---------+
2 rows in set (0.00 sec)
mysql> select * from t3;
+----+---------+
| sn | phoneNo |
+----+---------+
| 1 | 11 |
| 2 | 22 |
+----+---------+
2 rows in set (0.00 sec)
Session 2:
Database changed
mysql> delete from t3 where sn=2;
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
此时session 1看到的还是2条 表明RR是重复读
1.SELECT ... LOCK IN SHARE MODE 设置一个共享锁锁定在任何你要读的记录,其他session 只能读取记录,
因为不能修改它们直到你的事务提交。
如果任何其他记录被其他事务改变 没有被提交,你的查询等待直到那个事务借宿 然后使用最新的数据
mysql> select * from t3;
+----+---------+
| sn | phoneNo |
+----+---------+
| 1 | 11 |
| 2 | 22 |
+----+---------+
2 rows in set (0.00 sec)
mysql> select * from t3 LOCK IN SHARE MODE;
+----+---------+
| sn | phoneNo |
+----+---------+
| 1 | 11 |
| 2 | 99 |
+----+---------+
2 rows in set (4.78 sec)
看到的是最新的数据:
mysql> select * from t3;
+----+---------+
| sn | phoneNo |
+----+---------+
| 1 | 11 |
| 2 | 22 |
+----+---------+
2 rows in set (0.00 sec)
mysql> select * from t3 LOCK IN SHARE MODE;
+----+---------+
| sn | phoneNo |
+----+---------+
| 1 | 11 |
| 2 | 99 |
+----+---------+
2 rows in set (0.00 sec)
2.
mysql> select * from t3 where sn=2 for update --看到的也是最新的记录
-> ;
+----+---------+
| sn | phoneNo |
+----+---------+
| 2 | 99 |
+----+---------+
1 row in set (4.26 sec)
mysql>
mysql> select * from t3;
+----+---------+
| sn | phoneNo |
+----+---------+
| 1 | 11 |
| 2 | 22 |
+----+---------+
2 rows in set (0.00 sec)
对于所有搜索遇到, SELECT ... FOR UPDATE locks 锁定记录和任何相关的index entries,
相当于你执行一个update语句对于那些记录。
其他事务是被堵塞的来更新那些记录,做 SELECT ... LOCK IN SHARE MODE,
或者从读取的数据在某些事务隔离级别。
一直读忽略任何锁设置在记录上(老的记录不能被锁定,它们是应用undo log重构的)
当 LOCK IN SHARE MODE and FOR UPDATE 查询的索引锁是被释放放事务是被提交或者回滚
锁定记录用于更新使用SELECT FOR UPDATE 只使用与当autocommit 被关闭(或者开始事务使用START TRANSACTION or by setting autocommit to 0.
如果自动提交启用,匹配的记录不会被锁定)
SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE locks在RR模式下可以看到最新的记录
最新推荐文章于 2023-04-02 19:30:54 发布