这里是官方介绍文档
http://dev.mysql.com/doc/refman/5.6/en/innodb-locking-reads.html
需求
在一个事务中进行insert 或者update操作时,另外一个事务可以对同样的行进行update或者delete。 InnoDB 提供两种读锁提供保护。
- SELECT ... LOCK IN SHARE MODE 对读取的行加锁,其他的会话可以读这些行,但是不能修改这些行。 如果另一个会话已经修改了要读的行,那么你的读操作就需要等待直到另一个会话的修改操作commit
- SELECT ... FOR UPDATE 会将相关的行及索引锁定。其他的update事务会阻塞。 并且不能同时在多个事务中使用FOR UPDATE
必须set autocommit=0或者start transaction,两种锁才会有效
下面是进行实验的例子
首先创建一个表格,并插入若干的数据
CREATE TABLE IF NOT EXISTS `test1`(
`a` INT NOT NULL AUTO PRIMARY KEY,
`B` INT NOT NULL
)ENGINE=InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
INSERT INTO `test1` VALUES(NULL, 1);
INSERT INTO `test1` VALUES(NULL, 2);
INSERT INTO `test1` VALUES(NULL, 3);
INSERT INTO `test1` VALUES(NULL, 4);
INSERT INTO `test1` VALUES(NULL, 5);
1.SELECT ... LOCK IN SHARE MODE 一个事务申请之后,另外一个会话仍然可读,但是不能修改
session1 > BEGIN;
session1 > SELECT * FROM `test1` WHERE `a` = 1 LOCK IN SHARE MODE; #在另一个会话中可读
session2 > SELECT * FROM `test1` WHERE `a` = 1; #可以返回结果
session2 > UPDATE `test1` SET `b` = 2 WHERE `a` = 1; #error,无法修改,除非事务提交
session1 > commit;
2.SELECT ... LOCK IN SHARE MODE 可以同时在两个事务中申请共享锁, 但是FOR UPDATE就不行
session1 > BEGIN;
session1 > UPDATE `test1` SET `b` = 2 WHERE `a` = 1;
session2 > BEGIN;
session2 > SELECT * FROM `test1` WHERE `a` = 1 LOCK IN SHARE MODE;#会在次数一直阻塞,直到session1提交了会话
3.现在的mvcc通过写时复制技术,实现了 读读,读写,写读的串行。
如何查看是否使用了mvcc技术呢?
session 1 > BEGIN;
session 1 > SELECT * FROM `test1` WHERE `a` = 1;
+---+---+
| a | b |
+---+---+
| 1 | 2 |
+---+---+
session2 > UPDATE `test1` SET `b` = 3 WHERE `a`=1;
session2 > COMMIT;
session 1 > SELECT * FROM `test1` WHERE `a` = 1; #结果并没有改变,因为复制了一份
+---+---+
| a | b |
+---+---+
| 1 | 2 |
+---+---+
网友评论