mysql 起源&基础 🔗

创建表时的存储引擎 🔗
存储引擎-是创建表时设置,存储引擎是表级别的使用
mysql常见可配置的存储引擎:
- innodb
- 只有数据文件也是索引文件,聚集索引,一个表对应一个文件
- innodb存储引擎的文件结构
- 数据按行存储 类似网络协议栈,由页头,区头,段头,表头
- 表结构文件(user.frm, 表名 + .frm组成整个名称)
- 日志文件(redo文件等)
- mysiam
- 既有数据文件,又有索引文件
- 不支持事务
一般索引的结构 🔗
数据库系统内幕:存储引擎
单机角度介绍 磁盘存储格式,索引数据结构,事务处理。
其他的查询计划,查询优化等不介绍,
负责内存和磁盘上的存储、检索。
数据库是构建在存储引擎之上的,提供了表结构,sql,索引,事务等特性。
数据库使用文件来存储数据,但不依赖于目录和文件系统来定位数据。
- 红黑树,AVL等二叉树导致树的深度可能很深。
- 为了降低树的高度,多叉树。
- B树 mongodb,允许一个树节点中存多个数据,中间节点存了数据
- etcd
- B+树 innodb
- 只有叶子节点存数据
- 叶子节点根据key从小到大,叶子之间有指针,方便区间查询
- B树 mongodb,允许一个树节点中存多个数据,中间节点存了数据
sql优化 🔗
- 搜索字段上建索引,同时不在索引字段上使用聚合函数
- 避免select *,这样不能使用覆盖索引
- 在innodb引擎下,select a,b,c 可以走辅助索引找到所有的数据,避免走到聚集索引上,减少一次聚集索引查询过程
- 减少数据传输量,limit
- 不使用like ‘%xx’, 多用区间操作, 能用 between 就不要用 in
- 复合索引最左前缀 (不是指SQL语句的where顺序要和复合索引一致)
- 复合索引底层存储也是一颗B+树,只不过排序key=(a,b,c), 这样是复合索引使用时需要满足最左前缀的原理
- 避免使用子查询, 子查询产生的临时表再扫描无索引可走,会全表扫描
- explain 显示select语句的执行计划
- select_type: simple等
- type: 判断查询是否高效,const, ref, range, index,all
- extra: using index, using filesort(不能通过索引达到排序), using temporary(使用了临时表)
锁 🔗
参考 官网 mysql reference manual, innoDB Locking。
-
InnoDB 检索数据走索引是行锁,不走索引是表锁。
-
行级锁
- Record Lockx 对索引项加锁,锁定一条记录
- Gap Lockx 锁定一个范围,不包含记录本身
- Next-Key Lock = gap + record lock, 锁定一个范围 并锁定记录本身 左开右闭
(]
-
表级锁
-
死锁的必要条件:互斥,请求并保留,不剥夺,循环等待。
- show engine innodb status
- show open tables where in_use>0;
- show full processlist;
事务原理 🔗
- mysql transaction (ACID 锁、mvcc保证隔离性, undo log 保证原子和一致性,relog 保证持久性)
- 隔离级别在终端进行模拟
- 隔离级别:事务之间的可见性。 select @@global.tx_isolation
- read uncommited (tranx will read dity data)
- read committed (no repeatable read)
- 不可重复读(事务中两次读的结果不一致,事务执行select时没有获得读锁,或者释放了读锁)
- 事务1等读到事务2的commit, 从数据库对事务ACID角度上讲,违背了隔离性
- repeatable read (default mode)
- 在RR上事务启动时拿到数据库的一个静止快照
- 备份时需要一致性的读
- insert,delete存在幻读(innodb的间隙锁解决)
- seriablizable
- mvcc ( read-view 回滚段)
- Read View生成时机的不同,从而造成RC, RR级别下快照读的结果的不同
- 在RR级别下对第一次快照读会快照Read View,之后的快照读获取的都是同一个Read View。
- 在RC级别下的事务中可以看到别的事务提交的更新,每次快照读都会新生成一个快照和Read View。
- 重要的日志: undo log, redo log
- undo log:
- 记录某数据被修改前的值,可以用来在事务失败时进行rollback,帮助事务回滚
- undo log(undo data)中记录了历史版本,帮助实现MVCC功能, 保证原子性,一致性
- redo log:
- InnoDB将数据缓存到内存的buffer pool中,为保证事务的持久性,事务提交前先写redo log(WAL)持久化
- 记录的是页的物理修改操作(pageid, offset, field, value)
- log writer 线程确保redo log fsync操作写入磁盘
- undo log:
高可用与数据同步 🔗
- Master-Slave 原理 (Binlog, Relay log)
- 异步复制
- 主库
- 当从库连接时,binlog dump thread发送binlog event,并持有event的lock
- IO thread 读完后释放lock
- 从库
- IO thread读binlog event,生成relay log
- SQL thread 读relay log,执行
- 主库
- Binlog: SQL(增删改查,DDL)语句按 提交顺序 生成的日志,用于数据回滚,异步复制
- Binlog的3种存储格式:binlog_format(row, statement, mixed)
- statement格式: 每一条会修改数据的sql都会记录在binlog中
- row: 不记录sql语句上下文相关信息,仅保存哪条记录被修改
- mixed: 混合 (Binlog记录数据库发生的变化,用于replication)
- Binlog的3种存储格式:binlog_format(row, statement, mixed)
- Relay log: 通过异步复制Master中的binlog,生成slave的执行日志
- 异步复制
使用时注意 🔗
数据库使用自增主键作为唯一key时可能的问题: 当需要分库分表时,会出现主键重复。
- explain 看mysql的执行计划,是否走索引
- 字符类
- varchar(50)表示最大存放50个字符, char
- int(10)表示最大显示宽度为10,存储还是占4字节
- 时间日期类
- date, '1000-01-01' to '9999-12-31'
- datetime, '1000-01-01 00:00:00' t0 '9999-12-31 00:00:00',范围广
- timestamp, '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC
reference 🔗
《深入浅出MySQL 数据库开发、优化与管理维护》
CMU 15-445/645,MIT 6.172 Performance Engineering of Software Systems, Fall 2018