Mysql

Mysql

Mysql 有哪些引擎,分别有什么特点?


Mysql 索引是怎么实现的?


Mysql 事务是怎么实现的?

begin 命令并不代表事务的开始,事务开始于 begin 命令之后的第一条语句执行的时候。

begin;
select * from xxx;
commit; -- 或者 rollback;

Mysql 事务隔离级别有哪些?

隔离级别 脏读 不可重复读 幻读 备注
读未提交(READ UNCOMMITTED 不加锁
读提交 (READ COMMITTED × Oracle 默认
可重复读 (REPEATABLE READ × × Mysql 默认
串行化 (SERIALIZABLE × × × 共享锁 相当于单线程
  • 可重复读
    • 事务开始时读到的已有数据是什么,在事务提交前的任意时刻,这些数据的值都是一样的。

设置隔离级别

-- SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
set global transaction isolation level read committed;

查询当前有多少事务正在运行

select * from information_schema.innodb_trx;

可重复读

为了实现可重复读,MySQL 采用了 MVVC (多版本并发控制) 的方式

我们在数据库表中看到的一行记录可能实际上有多个版本,每个版本的记录除了有数据本身外,还要有一个表示版本的字段,记为 row trx_id,而这个字段就是使其产生的事务的 id,事务 ID 记为 transaction id,它在事务开始的时候向事务系统申请,按时间先后顺序递增。

快照,学名叫做一致性视图,这也是可重复读和不可重复读的关键,

  • 读提交是每次执行语句的时候都重新生成一次快照
  • 可重复读是在事务开始的时候生成一个当前事务全局性的快照

MySQL 的可重复读隔离级别其实解决了幻读问题

读提交解决了脏读问题,行锁解决了并发更新的问题。 并发写问题的解决方式就是行锁,而解决幻读用的是间隙锁, MySQL 把行锁和间隙锁合并在一起,解决了并发写和幻读的问题,这个锁叫做 Next-Key 锁

参考:

为什么 Oracle 等默认隔离级别是 READ COMMITTED ,而 Mysql 默认隔离级别是 REPEATABLE READ


Mysql 有哪些锁,各自的使用场景是什么?

行锁 表锁 页锁
MyISAM
BDB
InnoDB

BDB 已经被 InnoDB 所取代


  • 表锁
    • 开销小,加锁快;不会出现死锁;锁定力度大,发生锁冲突概率高,并发度最低
  • 行锁
    • 开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高
  • 页锁
    • 开销和加锁速度介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般

  • 共享锁(S)
  • 排他锁(X)
  • 意向共享锁(IS)
  • 意向排他锁(IX)

  • 行锁(Record Locks
    • 行锁一定是作用在索引上的
  • 间隙锁(Gap Locks
    • 间隙锁一定是开区间
    • 间隙锁的应用场景包括并发读取、并发更新、并发删除和并发插入
    • 可重复读串行化才有间隙锁读未提交读提交没有间隙锁
  • 临键锁(Next-key Locks
    • 临键锁是行锁 + 间隙锁,即临键锁是是一个左开右闭的区间
    • RR 级别下使用 select ... in share mode 或者 select ... for update 语句,那么 InnoDB 会使用临键锁,因而可以防止幻读读后写的场景)
      • RR 级别下使用普通的 select 语句,InnoDB 将是快照读,不会使用任何锁,因而还是无法防止幻读。
  • 共享锁 / 排他锁(Shared and Exclusive Locks
    • 共享锁 / 排他锁都只是行锁,与间隙锁无关
    • 共享锁:select ... in share mode
    • 排他锁:select ... for update
    • 尽管共享锁 / 排他锁是行锁,与间隙锁无关,但一个事务在请求共享锁 / 排他锁时,获取到的结果却可能是行锁,也可能是间隙锁,也可能是临键锁,这取决于数据库的隔离级别以及查询的数据是否存在
  • 意向共享锁 / 意向排他锁(Intention Shared and Exclusive Locks
    • 意向共享锁 / 意向排他锁属于表锁
    • 取得意向共享锁 / 意向排他锁是取得共享锁 / 排他锁的前置条件
  • 插入意向锁(Insert Intention Locks
    • 插入意向锁是一种特殊的间隙锁,该锁只用于并发插入操作
    • 如果说间隙锁锁住的是一个区间,那么插入意向锁锁住的就是一个点
  • 自增锁(Auto-inc Locks

  • 增:插入意向锁
  • 删改:排他锁
  • 查:共享锁

参考:


Mysql 什么情况下会出现死锁?

  • 在 InnoDB 引擎下,RR (REPEATABLE-READ) 级别,如果多个事务争抢同一个资源,会发生死锁。

next-key lock


Mysql 如何保证数据一致性?


Mysql 主从如何同步?