MySQL 知识点
一、索引
索引是帮助高效获取数据的数据结构。
1.索引分类:
- 从数据结构角度:B+Tree索引、hash索引、全文索引、R-Tree索引
- 从物理存储角度:聚簇索引和辅助索引(也叫二级索引、非聚簇索引)
- 从逻辑角度:主键索引、普通索引、复合索引、唯一索引、空间索引
2.解释
聚簇索引:聚簇索引是对磁盘上实际数据重新组织以按指定的一个或多个列的值排序的算法。它的特点是叶子节点中会存放当前主键所对应行的数据,查询是不用进行回表查询。主键索引就是聚簇索引。
非聚簇索引:非聚簇索引也称普通索引,它的特点是叶子节点中也会存放数据,与主键索引不同的是普通索引中存放的数据只有主键的值,而非整行记录的值。在查询时是先查到主键id,然后再根据id的值去主键索引树上查找这一整行其他字段的值,这个过程称之为回表。
覆盖索引(索引覆盖):即非主键索引中就能查到的记录,而不需要查询主键索引中的记录,避免了回表的产生减少了树的搜索次数,显著提升性能。
3.问题
3.1主键索引和唯一索引的区别:
主键索引就是唯一索引,但是唯一索引不一定是主键索引,唯一索引可以为空,但空值只能有一个,主键不能为空。
3.2索引失效的情况
- 查询条件中有or,及时其中有条件带索引也不会使用。
- 对于复合索引,违反最佳左前缀法则
- 在索引列上做计算、函数等操作
- 索引范围条件右边的列
- like以通配符开头 ,"%aa"
- 使用不等于(!=、<>)
- 字符串不加单引号
- 索引列有null值
参考文章:
https://juejin.im/post/6844904134433308685
https://mp.weixin.qq.com/s/_9rDde9wRYoZeh07EASNQQ
二、数据库的隔离级别
隔离级别 | 解释 | 引发问题 |
读未提交(READ UNCOMMITTED) | 事务A读取到事务B修改但未提交的数据 | 脏读、不可重复读、幻读 |
读已提交(READ COMMITTED) | 事务B只能在事物A修改过并且已提交后才能读取到事务A修改的数据 | 脏读、不可重复读 |
可重复读(REPEATABLE READ) | 事务B只能在事务A修改过数据并提交后,自己也提交事务后,才能读取到事务B修改的数据 | 幻读 |
序列化(SERIALIZABLE) | 各种问题(脏读、不可重复读、幻读)都不会发生,通过加锁实现(读锁和写锁) |
脏读:一个事务读到了另一个事务修改过未提交的数据
不可重复读:一个事务只能读到另一个已经提交的事务修改过的数据,并且其他事务每对该数据进行一次修改并提交后,该事务都能查询得到最新值
幻读:一个事务先根据某些条件查询出一些记录,之后另一个事务又向表中插入了一些符合条件的数据,原先的事务再次按照原来的条件查询时,把另一个新插入的数据也读了出来。
参考文章:https://developer.aliyun.com/article/743691
三、锁
锁机制分类:
读锁(read lock),也叫共享锁(share lock)。针对同一份数据,多个读操作可以同时进行而不会互相影响。
写锁(write lock),也叫排它锁(exclusive lock)。当前操作没完成之前,会阻塞其他读和写操作。
意向共享锁(IS), 一个事务给一个数据行加共享锁时,必须先获得表的IS锁。
意向排它锁(IX), 一个事务给一个数据行加排他锁时,必须先获得该表的IX锁。
按不同粒度分类:
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。这些存储引擎通过总是一次性同时获取所有需要的锁以及总是按相同的顺序获取表锁来避免死锁。表级锁更适合于以查询为主,并发用户少,只有少量按索引条件更新数据的应用,如Web 应用
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。最大程度的支持并发,同时也带来了最大的锁开销。在 InnoDB 中,除单个 SQL 组成的事务外,
锁是逐步获得的,这就决定了在 InnoDB 中发生死锁是可能的。行级锁只在存储引擎层实现,而Mysql服务器层没有实现。 行级锁更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
类型 | 读锁 | 写锁 |
表级锁 | 针对同一份数据,多个读操作可以同时进行而不会互相影响(select) | 当前操作没完成之前,会阻塞其它读和写操作(update、insert、delete) |
行级锁 | 允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁 | 允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享锁和排他锁 |
行锁加锁方式:
- 隐式上锁(默认自动加锁自动释放):select不会上锁, insert、update、delete上写锁
- 显示上锁:读锁,select * from tablename lock in share mode; 写锁,select * from tablename for update;
- 解锁(手动):1.提交事务(commit) 2.回滚事务(rollback) 3. kill 阻塞进程
问题:为什么上了写锁,别的事务还可以读操作?
因为InnoDB有MVCC机制(多版本并发控制),可以使用快照读,而不会被阻塞。
表锁的加锁方式:
-
隐式上锁(默认,自动加锁自动释放): select不会上锁, insert、update、delete上写锁
-
显式上锁(手动): 读锁: lock table tablename read; 写锁:lock table tablename write;
- 解锁(手动): unlock tables 所有锁表