MySQL复习

83 阅读6分钟
  • 为什么需要事务机制,以及事务的acid原则

  • 事务的隔离级别

  • 脏读,幻读和不可重复读是什么意思?

  • mysql的事务机制是如何实现的?

  • mysql的锁机制

  • 行锁和表锁有什么区别

  • mysql的行锁和表锁有哪些?

  • 记录锁,间隙锁和临键锁有什么区别

  • 隐式锁或手动加锁后,什么时候会释放锁?

  • mysql5.7引入的共享排他锁是干嘛的?

  • 什么是MVCC机制?

  • MVCC机制是如何实现的?

  • 事务隔离机制的底层实现是什么?

    1. 在进行业务操作时需要保持数据的一致性,acid有四个特性 原子性:指组成一个事务的一组sql要么全部执行成功,要么全部执行失败 一致性:指任何一个事务发生的前后,数据库内的数据变化必须一致 隔离性:指同时存在多个并发事务,各个事务之间的执行操作相互独立不会受其他事务执行的影响。 持久性:指一个事务提交后,就必须确保事务变更过的数据永远不会丢失。
    2. 事务的隔离级别一共有四个 读未提交:处于该隔离级别的数据库,脏读,不可重复读,幻读都可能发生 读已提交:该级别中解决脏读问题,不可重复读和幻读依旧存在 可重复读:该级别中解决脏读和不可重复读的问题,但幻读问题依旧存在 可串行化:该级别中解决脏读,不可重复读和幻读的问题
    3. 脏读:指一个事务读到了另一个事务还没提交的数据,其他事务可能会回滚这些数据。不可重复读:指在一个事务中多次读取同一数据,先后读取到的数据不一致。幻读:指一个事务中,批量变更了某类数据,变更完成后查询,表中依旧存在变更前的数据,就好像发生了幻觉一样。
    4. mysql的事务机制是innodb引擎独有的,事务机制是基于undo-log日志实现的,innodb引擎默认会开启事务的自动提交,将每条sql都视作一个事务,而通过begin指令开启事务后,需要手动提交才能生效,可以将多条sql组成一个事务。写入语句时会记录undo-log日志,更新数据前会把原来老的数据放在undo-log日志中,然后在表的数据行上记录一个回滚指针,这个指针会指向undo-log日志中的老数据,当事务需要回滚的时候,innodb会根据回滚指针的地址,找到原本老的数据,然后直接复制过来,将变更过的数据更新掉。
    5. 本质上是两种锁,排他锁和共享锁
  • 以锁的粒度划分

    • 表锁
      • 全局锁
      • 元数据锁
      • 意向锁
      • 自增锁
    • 行锁
      • 记录锁
      • 间隙锁
      • 临键锁
    • 页面锁
  • 以互斥性来划分

    • 共享锁
    • 排他锁
    • 共享排他锁
  • 以操作类型的维度划分

    • 读锁
    • 写锁
  • 以加锁方式的维度进行划分

    • 显式锁
    • 隐式锁
  • 以思想的维度进行划分

    • 乐观锁
    • 悲观锁
  1. 根据粒度的不同,表锁是指对一整张表加锁,当加锁后,其他来访问该表的事务都会被阻塞,而行锁的粒度更细,是指针对一条/多条数据加锁,并不会阻塞操作同一种表的事务,而仅仅只会阻塞操作相同行的数据的事务。

  2. 表锁有元数据锁,意向锁,自增锁和全局锁四种,行锁有记录锁,临键锁,间隙锁,插入意向锁这四类,行锁在mysql中是innodb所独有的,并且innodb的行锁和表锁之间是相互兼容的

  3. 记录锁是指对一条数据上锁,间隙锁是指对一条数据和下一条数据之间的空隙上锁,临键锁则是前两者的结合体,innodb的行锁默认就是临键锁类型,这三种锁都属于innodb行锁算法,innodb会根据情况来选择不同的行锁算法获取锁。

  4. 几乎所有释放锁的工作都是mysql自动完成的,但不同的事务隔离级别中,释放锁的时机也不同,如果目前是读未提交级别,mysql执行完一条sql语句后就会立马释放锁。如果是其他级别中,基本上都需要等待持有锁的事务结束后才会释放。

  5. 因为索引树的结构会发生变更,比如一个无序数据插入时,就会导致树节点的分裂,这时需要挪动树中的一些节点位置,为了防止其他事务再次破坏树结构,或从索引树中读到不对的数据,所以会对整棵树上锁,这个问题被称为SMO问题,共享排他锁主要是为了解决SMO问题。

  6. MVCC技术被称为多版本并发控制技术,是innodb中用来解决读-写事务并发冲突的问题,对于多事务并发执行的情况下,innodb引擎的表在更新某条数据时,并不会阻塞尝试读取这条数据的事务,而是会让读数据的事务去拿更新前的数据记录,实现读写事务的并发执行。

  7. MVCC机制是通过undo-log日志的版本链,数据表上的隐藏字段,以及ReadView读视图实现的,简单来说就是:写操作会直接对表数据进行变更,而读操作会根据回滚指针,去找到undo-log中的旧数据。

  8. mysql锁机制是基于事务实现的,一个事务尝试获取锁时,就会在内存中生成一个锁结构,锁结构中会记录着当前事务,要加锁的数据地址,会精确到表空间,数据段,数据页。行数的信息。同时锁结构中有一个is_waiting信息,为0表示当前锁结构对应事务持有着锁,而为1表示当前锁结构对应的事务在阻塞等待获取锁。一个事务尝试获取锁时,会根据要上锁的数据位置,去内存中看看是否已有对应数据位置的锁结构,如果有就代表自己要获取的锁,已经被其他事务锁占用,这时还要去看一下锁的比特位,看一下自己要获取的行锁,具体有没有被加锁,如果没有,当前事务直接获取锁执行,如果有,当前事务阻塞等待,对应的锁结构中的is_waiting=1。

  9. 每个事务隔离级别都是基于锁和MVCC机制实现的,读未提交:写操作加排他锁,读操作不加锁。读已提交:写操作加排他锁,读操作加MVCC机制,但每次select都生成一个读视图。可重复读:写操作加排他锁,读操作依旧采用MVCC机制,但一次事务中只生成一个读视图。序列化:所有写操作加临键锁,所有读操作加共享锁。