MySQL引擎
引擎 支持的索引 支持的锁 其他 innodb B-tree 行锁 MyIsAM BTree索引、RTree索引、Full-text索引 表锁 a.MyISAM是MySQL默认的存储引擎。MyISAM不支持事务、也不支持外键,其优势是访问的速度快,对事务完整性没有要求或者以 SELECT、INSERT 为主的应用基本上都可以使用这个引擎来创建表。b.生产环境,进行库读写分离,可以考虑使用,MyIsAM默认支持表级锁以上 memory hash索引、BTree索引 表数据存放于内存中在启动MySQL服务的时候使用–init-file选项,把 INSERT INTO … SELECT或LOAD DATA INFILE
MySQL索引数据结构
BTree索引
Mysql使用到索引的情况
匹配全值 匹配范围查询 最左匹配原则,联合索引中使用索引最左列进行查找 添加联合索引 index(a,b,c),当where a = XXX时查询使用了索引,当b=XX 或者 b=xxx and c= XXX时不使用索引。最左匹配原则为BTree索引使用的首要原则 当select查询的字段都是索引字段时,查询效率比较高,因为不需要通过索引再回去查表中对应的行数据 like查询索引字段,同时%在右边,在左边时不使用索引 能够实现索引匹配部分精准而其他部分访问查询 对索引字段where条件查询name is null
MySQL存在索引但不使用索引的情况
like查询以%开头 数据出现类型隐式转换时不使用索引,例如字段类型为字符串,where查询是name=3,name的值为整型,出现整型转字符串的隐式转换,不使用索引 联合索引不满足最左匹配原则 Mysql估计使用索引更耗时时则不使用索引。 Or查询时有后侧没有索引,若or后侧查询有索引在mysql分析使用索引查询更优时会使用索引
Hash索引
仅memory索引和Heap索引支持 Hash索引where语句不支持范围查找,>=操作 where语句中仅使用=时使用索引
RTree索引
Full-text索引
Mysql查询优化
MySQL锁
表级锁:开销小,加锁快,不会出现死锁;锁粒度大,发生锁冲突概率大,并发度低 行级锁:开销大,加锁慢,会出现死锁,锁粒度下,锁冲突概率小,并发度高
事务
ACID属性
事务带来的问题
事务隔离级别
在读数据前对数据加锁,阻止其他事务对数据进行修改 不加任务锁。一定机制生成一个数据请求时间点的一致性快照,利用这个快照提供给语句或者事务进行读取。也叫数据多版本并发控制(MVCC或MCC)
隔离级别 读数据一致性 是否支持脏读 是否支持不可重复读 是否支持幻读 未提交读(Read uncommitted) 最低级别,只能保证不读取物理上损坏的数据 是 是 是 已提交读(Read committed) 语句级 否 是 是 可重复读(Repeatable read) 事务机 否 否 是 可序列化(Serializable) 最高级别、事务级 否 否 否
MyISAM的锁
锁类型
MyISAM只支持表锁 两种表级锁:共享读锁,独占写锁 当session获取到共享读锁时,其他session可以读,可以获取独占写锁 当session获取到独占写锁时,仅当前session可以更新数据,其他session不可读,不可获取独占写锁
1.当session获取到一张表的共享读锁时,当前session无法查询和更新其他表,仅可以对当前表进行查询;
其他session可以查询表数据,更新session时将会出现等待现象。加读锁时需要对用到的所有表进行加锁操作。
2.MyISAM引擎是读写串行。current_insert参数设置为1时,运行进程读表的同时,另一个进行在表尾插入数据
MyISAM锁的调度
MyISAM引擎写锁优先级高于读锁,当读锁已经在等待队列时,写锁后到,写锁会插入到读锁前,造成读线程等待,因此MyISAM只适用于大量读的场景,更新多的场景不适应MyISAM引擎 MyISAM有参数设置优先级 当读操作较多,因MyISAM为表级锁,有些查询会拿不到锁。
InnoDb的锁
锁类型
共享读锁(S):行级锁 排他写锁(X):行级锁 意向共享读锁(IS):表级锁 意向排他写锁(IX):表级锁
锁的实现方式
innodb锁是通过对索引加锁的方式实现的。如果没有索引,innodb将会通过聚簇索引来对记录加锁 Record Lock:对索引加锁 Gap Lock:间隙锁,范围查找时,对第一条记录前和最后一条记录后的间隙加锁 Next-key Lock:索引项加锁和间隙加锁。一方面是为了防止出现幻读,当一个事务对数据进行范围查询时,其他事务在该范围写入了数据,再次读取出现幻读。另一方面为了故障通过日志恢复数据。 如果不通过索引条件检索数据,Innodb将会对表中所有数据加锁,实际等同于表锁,在排他锁情况时,如果一条数据在update,将会对整表加排他锁,其他事务无法对表进行读写 MySQL的行锁是针对索引加的锁,如果索引相同,哪怕对应的数据不同也会冲突 联合索引,如果一个索引对应的记录被锁定,通过其他索引进行操作,如果涉及相同数据,也会冲突