1. 什么是MVCC?
M VCC 多版本并发控制,是乐观锁的一种实现方式,可以做到读不加锁,读写不冲突,解决读-写冲突的无锁并发控制。注意:MVCC 只在 Read Commited 和 Repeatable Read 两种隔离级别下工作。
1、快照读:简单的select操作,不需要加锁,基于MVCC和undo log来实现的,读取的是记录的可见版本(有可能是历史版本)。
2、当前读:特殊的读操作,需要加锁,是悲观锁的实现,读取的是记录的最新版本,并且当前读返回的记录,都会加锁,保证其他事务不会再并发修改这条记录。当前读的场景如下:
- insert/update/delete
- select …for update
- select … lock in share mode
2. MVCC 解决的问题是什么
MVCC 是一种用来解决读写冲突的无锁并发控制,也哭是为事务分配单项增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照,所以 MVCC 可以为数据库解决以下问题:
- 在并发读写数据库时,可以做到读操作时不阻塞写操作,写操作也不阻塞读操作,提高了数据库并发读写的性能。
- 解决脏读、幻读、不可重复读等事务隔离问题,但是不能解决更新丢失问题。
三种数据库并发场景
- 读-读:不存在任何问题,也不需要并发控制
- 读-写:有线程安全问题,可以回造成事务隔离性问题,可能产生脏读、幻读、不可重复读等问题
- 写-写:有线程安全问题,可能存在更新丢失问题。
MVCC 的实现原理是基于三个隐藏字段(DB_ROW_JD,DB_TRX_ID,DB_ROLL_PTR),undo log , Read View
3. 索引设计的原则是什么
- 索引不是越多越好,可以创建组合索引,但是组合索引的列不宜太多;
- 更新频繁的字段不要有索引;
- 大文本、大对象不要创建索引;
- 基数较小的表,没必要创建索引;
- 索引列越短越好,可以指定为某些列的一部分,不用全部字段;
- 索引的列尽量出现在
WHERE
条件语句中或者连接子句中; - 定义有外键的列一定要创建索引
4. MySQL 的隔离级别
-
读未提交:可以看到别的事务未提交的修改,带来脏读的问题;
-
读已提交:只有别的事务提交之后才能看到相应的修改,解决脏读的问题,却带来不可重复读的问题(前后两次读取的数据不一致,可能是在读取间隙,别的事务
update
修改了数据) -
可重复读:多次读取的数据一致,但是可能造成幻读(多次读取间隙别的事务
insert
了数据)MySQL 的 Innodb 采用了MVCC(多版本并发控制)来解决不可重复读的问题。具体地,MVCC 在每行数据后面增加了隐藏的两列(创建版本号和删除版本号),每个事务在开始的时候都会有一个递增的版本号。查询操作为了避免查询到旧数据或者已经被其他事务修改的数据,需要满足以下条件:
- 查询时当前事务版本号需要大于等于创建版本号;
- 查询时当前事务版本号需要小于删除版本号。
-
可串行化:这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
5. 聚簇索引和非聚簇索引
- 聚簇索引:数据跟索引是聚集存储的,eg: innodb 的主键索引就是聚簇索引。
- 非聚簇索引:数据跟索引不是聚集存储的:myisam 都是非聚簇索引;innodb 的二级索引(辅助索引、普通索引)也是非聚簇索引。