MySQL 2025-10-18 · 15 min 阅读

MySQL 索引和锁


索引基础

mysql索引存储使用N叉树,以InnoDB为例,当树的高度是4时,九可以存1200的3次方个值,大概17亿,查找一个值最多只需要访问3次磁盘。

索引类型分为主键索引和非主键索引,在InnoDB里,主键索引也被称为聚簇索引,其存储整行数据。非主键索引也被称为二级索引起叶子结点存的是主键的值,在基于二级索引查询时,会进行一次回表。

当sql语句只查询ID字段时,由于ID字段已经在k索引树上,不需要回表查询,索引k已经覆盖了我们的查询需求,称之为覆盖索引。

select ID from idx_T where k between 3 and 5;

最左前缀:mysql索引的最左前缀匹配原则,建立了(name, age)这个联合索引。当查找条件是”查所有姓名是张三”或”姓名的第一个字是张”都会走这个索引。

规则,这个最左前缀可以是联合索引的最左N个字段,也可以是字符串索引的最左M个字符。

在mysql 5.6引入了索引下推(index condition pushdown),可以在索引遍历过程中,对索引中包含的字段先做哦安段,过滤不满足条件的记录,减少回表次数。

mysql的锁

1、全局锁,命令是:flush tables with read lock,当你需要让整个库处于只读状态时,可以使用这个命令。之后,其它线程的:数据更新语句、数据定义语句和更新类事务的提交语句都会被阻塞。

mysql的逻辑备份工具mysqldump使用参数--single-transaction导数据之前就会启动一个事务,来确保拿到一致性视图。而由于MVCC的支持,这个过程中数据是可以正常更新。

2、表级锁有两种,一种是表锁,一种是元数据锁。

表锁的语法是lock tables ...read/write,可以使用unlock tables主动释放锁。需要注意,lock tables语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。

另一个表级的锁是MDL,在访问一个表的时候会被自动加上。MDL的作用是,保证读写的正确性。在加上MDL锁期间,不允许另一个线程对表结构做变更。

2、行锁,MySQL的行锁是在引擎层由各个引擎实现的,MyISAM不支持行锁,InnoDB是支持行锁的。

# 在第二个窗口中,针对于id = 200这一行的update,事务阻塞住了。
update t_idx set k=k+2 where id = 200;

死锁和死锁检测,当出现死锁时,有两种策略:

# MySQL# 大数据