mysql-1

82 阅读4分钟

mysql架构

客户端<+++连接器+++>server+存储引擎

1条MySQL语句怎么执行(结构)

结论 连接器、分析器 优化器 执行器
连接器:同一个连接的权限在连接器连接时确定,中途修改权限必须重新连接才能生效 分析器:词法分析(字符串识别成表名、列名等)+语法分析
优化器:结果就是生成一个执行计划:决定使用索引,决定join连接顺序
执行器:检查权限,打开表\

1条MySQL语句怎么更新(日志系统)

结论:上一条+写日志[先写日志,再写磁盘] redolog:InnoDB提供物理日志(重做日志),记录数据做了什么修改,循环写。需要更新写redo日志,更新内存,不忙时候写回磁盘,异常重启后redolog还在,提交记录不丢失。
binlog:MySQL server提供逻辑日志(归档日志),记录操作逻辑,追加写。
为了数据库一致性,采用两阶段提交:写入redolog到prepare状态,写入binlog后到commit状态\

事务隔离

ACID(I)

隔离级别:

  • 读未提交:事务未提交,其更改可被其他事务看到
  • 读提交:事务提交,其更改才会被其他事务看到
  • 可重复读:一个事务执行过程看到的数据,与事务启动时看到的数据一致
  • 串行化:加锁,读写冲突必须等待。

不要用长事务

占用存储空间,占用锁资源

索引

常见模型

类别特性
哈希KEY-VALUE,适用于等值查询
有序数组等值和范围查询,适用于静态存储引擎
N叉树B+树读写性能,适配磁盘访问模式

InnoDB索引

  1. 主键索引叶子节点是整行数据,非主键索引叶子节点是主键值,非主键索引查询需要多扫描一棵索引树。
  2. B+树插入删除数据需要页分裂、合并等操作,因此递增索引插入都是追加操作,不会导致叶子节点分裂

下(联合索引技巧)

  1. 索引覆盖:查询条件是普通索引,查询结果是联合索引的字段,不用回表直接返回
  2. 最左前缀:联合索引的最左N字段,字符串索引最左M字段
  3. 联合索引:根据联合索引的顺序,以最左原则检查
  4. 索引下推:like 'hello%’and age >10 检索,MySQL5.6版本之前,会对匹配的数据进行回表查询。5.6版本后,会先过滤掉age<10的数据,再进行回表查询,减少回表率,提升检索速度。

MYSQL锁

全局锁 备份

对数据库实例加锁,flush tables with read lock,全库处于只读状态
场景:不支持事务的引擎,全库逻辑备份
支持事务后,用可重复读隔离级别开启事务single transaction备份即可,主库更新等操作不受影响\

表级锁

表锁

语法: lock tables read/write

元数据锁MDL

自动添加,不需 要显示执行
作用:保证读写正确性
增删改查用读锁,表结构变更用写锁
读锁之间不互斥,读写锁、写锁之间互斥
问题:事务的MDL锁语句开始时执行,语句结束不被释放,等事务结束才释放,可能导致后续事务一直阻塞等待。
解决方案:(写锁)数据变更过程,设定等待时间,拿不到锁先放弃

行锁

两阶段锁

行锁需要等到事务结束才释放。因此把最可能造成冲突,影响并发度的锁往后放。

死锁&&死锁检测

处理死锁策略

  1. 等待到超时
  2. 死锁检测,发现死锁,回滚链条中的某一个事务

减少锁冲突

将一行改成逻辑上多行,减少锁冲突。
本质:控制相同资源的并发事务量

再谈事务隔离

再谈查询和更新两个操作的事务隔离

快照

InnoDB给每个事务分配一个id:row trx_id,一个数组记录启动时全部活跃的事务
每个数据都有多个版本,用row trx_id来区分,undolog就是通过版本间的变化来存储记录的\

更新

事务更新先读后写,读就是读当前值,当前读。
注意: 若select加锁,也是当前读

可重复读的核心就是一致性读(consistent read);而事务更新数据的时候,只能用当前读。如果当前的记录的行锁被其他事务占用的话,就需要进入锁等待。\

  • 对于可重复读,查询只承认在事务启动前就已经提交完成的数据;
  • 对于读提交,查询只承认在语句启动前就已经提交完成的数据;
  • 而当前读,总是读取已经提交完成的最新版本。