Mysql学习笔记(一)

Mysql

事务的基本要素

原子性,一致性,隔离性,持久性——-ACID

  1. 原子性(atomicity),即事务是一个原子操作单元,对数据的修改,要么全部执行,要么全部不执行
  2. 一致性(consistency),即事务开始与结束前,数据库的完整性约束未被破坏
  3. 隔离性(isolation),即同一时间,只允许一个事务请求同一数据,不同事务间没有任何干扰
  4. 持久性(durability),即事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚

事务的并发问题

脏读,不可重复读,幻读

  1. 脏读,即事务A读取了事务B更新的数据,然后B进行了回滚,那A读取到的数据是脏数据

  2. 不可重复读,即事务A多次读取同一数据,事务B在A多次读取过程中,对数据做了更新并提交,导致A多次读取的内容不一致

  3. 幻读,即事务A读取了事务B已提交的新增数据.也是重复读取不一致.

    幻读是新增数据,不可重复读是更改数据.

Mysql事务的隔离级别

读未提交:可以读到未提交的内容,可能产生脏读,不可重复读,幻读

不可重复读(读提交):只能读到已提交的内容

可重复读:查询事务启动时,不允许进行更改操作了,为Mysql的默认隔离级别

串行化: 数据库最高隔离级别,事务必须一个一个排队执行,按串行化顺序

  1. 为何出现脏读? select操作没有规矩
  2. 为何出现不可重复读? update操作没有规矩
  3. 为何出现幻读? insert和delete没有规矩
事务隔离级别 脏读 不可重复读 幻读
读未提交
不可重复读(读提交)
可重复读
串行化

sql语句执行顺序

from

where

group by

having

select

order by

Mysql的存储引擎

InnoDB

是基于聚簇索引建立的,其支持事务,外键,并且通过MVCC来支持高并发以及索引数据一体存储.Mysql5.5.8版本后成为默认存储引擎

MyISAM

为5.1版本前的默认引擎,支持全文检索,压缩,空间函数,但不支持事务和行级锁,一般用在大量查询少量插入的场景,且不支持外键,其索引和数据是分开存储的

Mysql的逻辑结构

最上层服务类似CS结构,进行连接处理,授权处理

第二层为Mysql服务层,SQL语句的解析分析优化,存储过程触发器视图等都在本层实现

最下层为存储引擎的实现,类似Java接口实现,在调用时会屏蔽不同引擎实现间的差异

Mysql的日志系统

undo log

即回滚日志文件,主要用于事务执行失败,进行回滚,在MVCC中对数据历史版本查看.由引擎层的InnoDB引擎实现,为逻辑日志,记录数据被修改前的值.保证了事务的一致性

redo log

即重做日志文件,记录数据修改后的值,用于持久化到磁盘中,由引擎层的InnoDB引擎实现,是物理日志,记录的是物理数据页修改的信息(诸如某个数据页上的内容发生改动).当某条数据需要更新,InnoDB会先将数据更新,然后记录redo log在内存中,找个时间将redo log操作执行到磁盘文件上.不管提交是否成功,都会记录,若进行回滚操作,也会记录回滚.保证了事务的持久性.

MVCC(多版本并发控制)

是Mysql中基于乐观锁理论实现隔离级别的方式,用于读提交和可重复读隔离级别的实现.在Mysql中,会在表中每条数据后添加两个字段:最近修改改行数据的事务ID指向改行回滚段(undolog)的指针.实际上为保存了数据在某个时间节点的快照.

binlog与redo log区别

  1. redo log是在InnoDB存储引擎层产生,而binlog是MySQL数据库的上层服务层产生
  2. 两种日志记录内容形式差异.binlog是逻辑日志,记录对应的sql语句和事务;而redo log是物理日志,记录的是关于每个页的更改的物理情况
  3. 两种日志的记录写入磁盘的时间点不同,binlog只在事务提交完成后进行一次写入.而redo log在事务进行中不断被写入.
  4. binlog不是循环使用,在写满或重启后,才会生成新的binlog文件,redo log是循环使用
  5. 两者都能进行数据恢复.

Mysql如何保证一致性和持久性

为保证ACID中的一致性和持久性,使用了先写日志再写磁盘的操作,即WAL(write-Ahead logging)

当数据库断电再重新启动时,mysql可以通过redo log还原数据;即只要在每次事务刷新时,同步刷新redo log即可,不用同步刷新磁盘数据文件.

Mysql锁的类型

mysql的锁分为共享锁和排他锁,即读锁和写锁.

读锁为共享的,可通过lock in share mode实现,只能读不能写

写锁为排他的,会阻塞其他的写锁和读锁.

另外,通过颗粒度来分,又分为表锁和行锁两种.

其中表锁会锁定整张表并阻塞其他用户对该表所有的读写操作.阻塞诸如alter修改表结构等的操作

行锁又可分为乐观锁和悲观锁两种,悲观锁通过for update实现,乐观锁通过版本号实现.

InnoDB的行锁模式

  1. 共享锁(S):用法即lock in share mode,允许一个事务去读一行,阻止其他数据获得相同数据的排他锁.意思是,若事务1对数据对象A加了S锁,事务1可以读A但不能修改A,其他事务对A也只能加S锁,而不能加X锁,直至事务1释放A上的S锁
  2. 排他锁(X):用法for update,允许获取排他锁事务更新数据,阻止其他事务对相同数据加锁.若事务1对数据A进行加锁,其他事务不能再对A加任何锁.

在没有索引的情况下,InnoDB只能使用表锁

Mysql的索引

索引按照数据结构来讲,主要包含B+树和Hash索引

为什么选择B+树为索引结构

  • Hash索引:Hash索引底层是哈希表,哈希表是一种以key-value存储数据的结构,所以多个数据在存储关系上是完全没有任何顺序关系的,所以,对于区间查询是无法直接通过索引查询的,就需要全表扫描。所以,哈希索引只适用于等值查询的场景。而B+ 树是一种多路平衡查询树,所以他的节点是天然有序的(左子节点小于父节点、父节点小于右子节点),所以对于范围查询的时候不需要做全表扫描
  • 二叉查找树:解决了排序的基本问题,但是由于无法保证平衡,可能退化为链表。
  • 平衡二叉树:通过旋转解决了平衡的问题,但是旋转操作效率太低。
  • 红黑树:通过舍弃严格的平衡和引入红黑节点,解决了 AVL旋转效率过低的问题,但是在磁盘等场景下,树仍然太高,IO次数太多。
  • B+树:在B树的基础上,将非叶节点改造为不存储数据纯索引节点,进一步降低了树的高度;此外将叶节点使用指针连接成链表,范围查询更加高效

B+树的叶子节点都可以存哪些东西

可能存储的是整行数据,也有可能是主键的值。B+树的叶子节点存储了整行数据的是主键索引,也被称之为聚簇索引。而索引B+ Tree的叶子节点存储了主键的值的是非主键索引,也被称之为非聚簇索引


本博客所有文章除特别声明外,大部分为学习心得,欢迎与博主联系讨论