Java八股文系列一(mysql篇)

目录

事务

四大属性

事务隔离

幻读

锁种类

共享锁、排它锁

记录锁(Record Locks)

间隙锁(Gap Locks)

临键锁(Next-Key Locks)

索引

聚簇索引和非聚簇

Inndb的表是否必须要聚簇索引

辅助索引

数据结构

B+树

MVCC

设计优化

三范式

QA

回表查询

深分页

索引失效


前言

mysql是web应用程序必备的数据库之一,学习mysql的实现原理帮助我们快速深入理解mysql的运行机制。

事务

四大属性

  1. 原子性(Atomicity)

        原子性是指事务是一个不可分割的工作位,事中的操作要么都生,要么都不生。通undolog实现

  1. 一致性(Consistency)

        事务前后数据的完整性必须保持一致。

  1. 隔离性(Isolation)

        事务的隔离性是多个用发访问数据库时,数据库为每一个用开启的事,不能被其他事的操作数据所干,多个并要相互隔离。通和MVCC实现

  1. 持久性(Durability)

        持久性是指一个事务一旦被提交,它数据中数据的改就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。通redo log实现

事务隔离

https://pics2.baidu.com/feed/9e3df8dcd100baa1c6a33b1b9278221bc9fc2e70.jpeg@f_auto?token=09badc938db596af4d3fa49ff601e475

幻读

  • 使用“串行化”隔离级别: 将事务隔离级别设置为“串行化”,可以避免幻读问题,但会影响并发性能。
  • 使用锁: 在查询操作时对相关数据行加锁,可以阻止其他事务对这些数据行进行插入或删除操作。
  • 使用MVCC(多版本并发控制): MySQL中使用MVCC可以在一定程度上解决幻读问题,通过使用版本号控制事务间的隔离。
  • 使用索引覆盖扫描: 使用覆盖索引扫描可以减少查询的范围,从而降低幻读的概率。

共享锁、排它锁

InnoDB 实现了标准级锁,包括两种:共享 s 锁)排它 x 锁)

-- 加共享锁(S)

select * from table_name where ... lock in share mode

-- 加排它锁(X)

select * from table_name where ... for update

级锁(MyISAM)、行级锁(InnoDB)页级锁(BerkeleyDB)

记录锁(Record Locks)

记录锁其实很好理解,对表中的记录加锁,叫做记录锁,简称行锁。比如

SELECT * FROM `test` WHERE `id`=1 FOR UPDATE;

它会在 id=1 的记录上加上记录锁,以阻止其他事务插入,更新,删除 id=1 这一行。

需要注意的是:

  • id 列必须为唯一索引列或主,否上述句加的就会临键锁(有关临键锁下面会讲)
  • 时查询语句必须为精准匹配(=,不能为 ><like等,否也会退化成临键锁

Gap Locks

间隙锁 是 Innodb 在 RR(可重复读) 隔离级别 下为了解决幻读问题时引入的锁机制。间隙锁是innodb中行锁的一种

请务必牢记:使用间隙锁锁住的是一个区间,而不仅仅是这个区间中的每一条数据

举例来说,假如emp表中只有101条记录,其empid的值分别是1,2,...,100,101,下面的SQL:

SELECT * FROM emp WHERE empid > 100 FOR UPDATE

当我们用条件检索数据,并请求共享或排他锁时,InnoDB不仅会对符合条件的empid值为101的记录加锁,也会对empid大于101(这些记录并不存在)的“间隙”加锁。

临键锁Next-Key Locks

Next-key锁是记录锁和间隙锁的组合,它指的是加在某条记录以及这条记录前面间隙上的锁

也可以理解为一种特殊的间隙锁。通过临建锁可以解决幻读的问题。 每个数据行上的非唯一索引列上都会存在一把临键锁,当某个事务持有该数据行的临键锁时,会锁住一段左开右闭区间的数据。需要强调的一点是,InnoDB 中行级锁是基于索引实现的,临键锁只与非唯一索引列有关,在唯一索引列(包括主键列)上不存在临键锁

索引

聚簇索引和非聚簇

聚簇索引叶子点存放一整行数据。非聚簇索引存放的是聚簇索引的key。InnDB主键使用的就是聚簇索引。MyISAM不管是主键索引,还是二级索引使用的都是非聚簇索引。

InnfoBD的聚簇索引是按主键顺序构建的B+tree.B+tree的叶子点就是行记录,行记录和主键紧凑的存储在一起。

Inndb的表是否必须要聚簇索引

  1. 如果表定了主索引就是聚簇索引。
  2. 如果表没有定第一个非空unique列作聚簇索引
  3. 建一个藏的row-id作聚簇索引

助索引

        也叫二级索引,是根据列索引构建B+tree构。但在B+tree的叶子点中只存了索引列和主的信息。二索引占用的空会比聚簇索引小很多。可以建多个助索引。

数据结构

B+树

        InnoDB 引擎存储数据的时候,是以页为单位的,每个数据页的大小默认是 16KB,即四个块。在B+树中,一个结点就是一页。非叶子结点由主键值和一个指向下一层的地址的指针组成的组合组成。叶子结点中由一组键值对和一个指向该层下一页的指针组成,键值对存储的主键值和数据。由存储结构,可以大概计算出一个B+树能存储的数据数量。

指针在InnoDB中为6字节,设主键的类型是bigint,占8字节。一组就是14字节。计算出一个非叶子结点可以存储16 * 1024 / 14 = 1170个索引指针。假设一条数据的大小是1KB,那么一个叶子结点可以存储16条数据。得出两层B+树可以存储1170 x 16 = 18720 条数据。三层B+树可以存储1170 x 1170 x 16 = 21902400条数据。

MVCC

        Multi-Version Concurrency Control,MVCC只在读取已提交(Read Committed)和可重复读(Repeatable Read)两个事务级别下有效。

设计优化

三范式

第一范式(1NF):表的数据不可分,数据项不可分。

第二范式(2NF):实体属性完全依赖主关键字。

第三范式(3NF):数据表中的字段不能有依赖传递

QA

回表查询

        通过普通索引查询方式,则需要先搜索该索引树,然后得到主键 ID的值,再到 ID 索引树搜索一次。这个过程虽然用了索引,但实际上底层进行了两次索引查询,这个过程就称为回表。

深分页

        查询偏移量过大的分页会导致数据库获取数据性能低下,以如下SQL为例:

SELECT * FROM t_order ORDER BY id LIMIT 1000000, 10

这句SQL会使得MySQL在无法利用索引的情况下跳过1000000条记录后,再获取10条记录,其性能可想而知。这种查询偏移量过大的场景我们称为深分页。

MySQL的深分页会带来性能下降等问题,而这个问题在分布式数据库场景下,会变得更加复杂。

索引失效

  1. 使用or
  2. 复合索引会失效
  3. like查询
  4. 索引查询时使用函数
  5. 隐式类型转换
  6. 对索引进行表达式计算

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值