可以把锁定读的执行看成是依次读取若干个扫描区间中的记录
在隔离级别不大于READ COMMITTED时,会为当前记录加记录锁。在隔离级别不小于REPEATABLE READ 时,会为当前记录加next-key锁。
索引下推是把与被使用索引有关的搜索条件下推到存储引擎中判断,而不是返回server层再判断。索引下推只是为了减少回表次数,也就是减少读取完整的聚簇索引记录的次数,从而减少I/O操作。所以只适用二级索引,不适用于聚簇索引。索引下推仅适用于SELECT语句,不适用于UPDATE、DELETE这些需要改动记录的语句。
如果该记录符合边界条件,则跳到步骤6执行,否则在隔离级别不大于READ COMMITTER时,就要释放掉加在该记录上的锁。在隔离级别不小于RR时,不释放加在该记录上的锁,并且向server层返回一个查询完毕的信息
除了索引下推中的条件以外,server层还需要判断其他搜索条件是否成立。如果成立,则将该记录发送到客户端,否则在隔离级别不大于READ COMMITTER时,就要释放掉加在该记录上的锁。在隔离级别不小于RR时,不释放加在该记录上的锁
实例---如果走的是二级索引,存在索引下推的情况分析
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for hero -- ---------------------------- DROP TABLE IF EXISTS `hero`; CREATE TABLE `hero` ( `number` int NOT NULL, `name` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, `country` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, PRIMARY KEY (`number`) USING BTREE, INDEX `idx_name`(`name` ASC) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of hero -- ---------------------------- INSERT INTO `hero` VALUES (1, 'l刘备', '蜀'); INSERT INTO `hero` VALUES (3, 'z诸葛亮', '蜀'); INSERT INTO `hero` VALUES (8, 'c曹操', '魏'); INSERT INTO `hero` VALUES (15,'x荀彧', '魏'); INSERT INTO `hero` VALUES (20, 's孙权', '吴'); SET FOREIGN_KEY_CHECKS = 1;
SELECT * FROM hero FORCE INDEX(idx_name) WHERE name > 'c曹操' AND name <='x荀彧'AND country !='吴' LOCK IN SHARE MODE
对name值为'l刘备'的二级索引记录进行分析
对name值为's孙权'的二级索引记录进行分析
对name值为'x荀彧'的二级索引记录进行分析
对name值为'z诸葛亮'的二级索引记录进行分析
需要注意的是:对于 孙权的二级索记录以及对应的number=20的聚簇索引记录,都是先加锁后释放锁。对应'z诸葛亮'的二级索引在步骤三被判断不符合边界条件,而且该步骤并不会释放加在该记录上的锁,而是直接向server层报告'查询完成'信息,因此导致整个语句在执行结束后也不会释放加在name值为'z诸葛亮'的二级索引记录上的锁。
对name值为'l刘备'的二级索引记录进行分析
对name值为's孙权'的二级索引记录进行分析
对name值为'x荀彧'的二级索引记录进行分析
对name值为'z诸葛亮'的二级索引记录进行分析
在隔离级别不小于RR的情况下,该语句在执行过程中对'l刘备,S孙权,X荀彧,Z诸葛亮'的二级索引记录都加上S型next-key锁,对number值为1、15、20的聚簇索引记录加S型正经记录锁。
Update语句加锁的方式与SELECT...FOR UPDATE类似,不同的是,如果更新了二级索引列,那么所有被更新的二级索引记录在被更新之前都需要加入X型正经记录锁。
UPDATE hero SET name = 'cao曹操' where number > 1 AND number <=15 AND country = '魏'
因为会更新name列,所有在更新前需要为idx_name二级索引中对应的记录加锁。
在不大于RC级别下该语句会给 'c曹操'和'x荀彧'的聚簇索引记录和二级索引记录加锁,对于number = 3的记录来说,由于它不符合country='魏'这个条件,所以先加锁后释放锁。对于number = 20的聚簇索引记录来说,由于不符合边界条件,所以也是先加锁后释放锁。
在不小于RR级别下,number列 number = 3、8、15、20列会被加上next-key锁,二级索引列name ='c曹操'、'x荀彧'会被加上X型的记录锁
加锁分析:
UPDATE hero SET name = 'cao曹操' where number > 1 AND number <=15 AND country = '魏'
对于Delete语句,加锁的方式与SELECT...FOR UPDATE语句类似,只不过如果表中包含二级索引,那么二级索引记录在被删除之前都需要加上X型记录锁。