《高性能Mysql(第三版)》
反模式:如果完全按照三大范式来设计表结构,会导致业务涉及表增多,查询数据需要多表联合查询,导致sql复杂,性能变差,不利于维护,也不利于分库分表,比如会在表中冗余存储城市id对应的城市名称
http://blog.720ui.com/2017/mysql_core_07_anti-pattern/
逻辑存储单元分为表空间(TableSpace) -> 段(segment) -> 区(extent) -> 页(page)
Mysql 8.0 InnoDB架构图
相关教程参考:https://blog.csdn.net/demonson/article/details/79863166
独立表空间
设置参数innodb_file_per_table = 1 ,目前MySQL默认都是独立表空间,每个表都有自己的表空间文件,存储对应表的B+数数据、索引和插入缓冲等信息,其余信息还是存储在共享表空间中
撤销表空间
包含撤销日志,初始化的时候会创建两个默认的撤销表空间
通用表空间
可以存储多个表的数据,相比独立表空间更节约元数据的内存开销
临时表空间
分会话临时表空间和全局临时表空间。会话临时表空间,在第一个请求中,会话临时表空间从临时表空间池分配给会话,最多两个临时表空间,一个用于用户创建的临时表,另一个用于优化器创建的内部临时表,当会话断开时,临时表空间将被释放进入临时表空间池中;全局临时表空间,用于存储用户创建的临时表的更改数据,用于回滚,在正常关闭或初始化中止时被删除,并在每次启动服务器时重新创建
ACID:
原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability)
存储引擎 | InnoDB | MyISAM |
---|---|---|
存储文件 | .frm表定义文件 .ibd数据文件 | .frm表定义文件 .myd数据文件 .myi 索引文件 |
锁 | 表锁,行锁 | 表锁 |
事务 | ACID | 不支持 |
CRUD | 读写 | 读多 |
count | 扫表 | 专门存储的地方 |
索引结构 | B+Tree | B+Tree |
https://blog.csdn.net/wuseyukui/article/details/72312574
B+Tree索引:
分两类,聚集索引和 普通索引
聚集索引,在创建表的时候,会创建一个主键,这个主键就是聚集索引,在索引叶子节点中存放了数据信息。InnoDB会给没有创建主键的表选择第一个不包含null值的唯一索引作为主键,如果唯一索引也没有,就会为该表创建一个6字节的rowid作为主键
普通索引,索引叶子节点并不包含所有行的数据,只保留键值,通过键来查找行数据
哈希索引:
查询当前会话级别:select @@tx_isolation;
查看系统当前隔离级别:select @@global.tx_isolation;
设置当前会话隔离级别:set session transaction isolatin level repeatable read;
设置系统当前隔离级别:set global transaction isolation level repeatable read;
MVCC即多版本并发控制,它能在很多情况下避免加锁操作,降低开销,不同的存储引擎实现方式不同,有乐观并发控制和悲观并发控制
MySQL的InnoDB引擎,通过在每行记录后面保存两个隐藏的列来实现,一个列保存了行的创建时间,一个保存了行的过期时间(或删除时间)。实际存储的是系统版本号,每开始一个新的事务,系统版本号都会自动递增,事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。该MVCC只使用在repeatable read 和 read committed下
保存这两个额外的系统版本号,使大多数读操作都不用加锁,并且也能保证只会读到符合标准的行。缺点是需要额外的存储空间和维护工作。
死锁是两个或者多个事务在同一资源上互相占用,并请求锁定对方资源,从而导致互相等待的现象。
死锁示例:
#事务1
start transaction;
update stockprice set close = 45 where stock_id = 4 and date = '2019-1-1';
update stockprice set close = 20 where stock_id = 3 and date = '2019-1-3'
#事务2
start transaction;
update stockprice set high = 36 where sockt_id = 3 and date = '2019-1-3';
update stockprice set hight = 60 where stock_id = 4 and date = '2019-1-1';
两个事务分别执行两个更新语句,都执行第一个语句,锁定了该行数据,但该行数据将做为对方事务执行下条语句的条件,所以当事务继续执行第二条语句的时候,因为需要的条件所在行已被另外一个事务锁定,这是死锁现象
避免死锁的方法:
select name,sex,rating from mysql_test a inner join (
select id from mysql_test where sex='F' order by rating limit 20000,100
) as x USING(id)
先查看type列,如果出现all关键词,就代表sql执行全表扫描
再看key列,如果null代表没有使用索引
再看rows列,如果越大,代表需要扫描的行数越多,相应耗时就长
最后看 extra列,是否有影响性能的 Using filesort 或者 Using temporary
explain 各个字段含义:https://blog.csdn.net/weixin_34062469/article/details/94498678
不一样,返回的结果不一样。
select * from a left join b on 条件 会返回 a 中没有匹配的数据
select * from a left join b where 条件 只返回where中匹配的数据
https://www.cnblogs.com/caowenhao/p/8003846.html
持续更新地址 语雀:https://www.yuque.com/itsaysay/mzsmvg GitHub: https://github.com/jujunchen/Java-interview-question