假如 有100万条数据,在mysql数据库中是如何存储的? 如何在高并发的情况下对一条数据进行操作?
数据库
1、数据库概念
数据库是三层架构中用于永久存储数据的仓库,就是存储数据的容器
2、数据库的三范式
确保数据库中每一列数据都是不可分割的原子性
数据表中每一列数据都应该和主键直接相关,即只能存储一种数据,不能存储多个数据
数据表中每一列数据都要和主键直接相关,而不是间接相关
3、软件的三层架构
用户交互界面:展示用户输入的信息和想要得到的数据
业务处理层: 处理用户发送的数据,进行相应的逻辑操作
数据库层:对用户的信息进行保存,返回结果
4、关系型数据库和非关系型数据库的优缺点
5、一条sql语句的执行过程
数据库的引擎
1、数据库引擎概念
数据库引擎是用于存储数据、管理和保护数据的核心服务,利用数据库引擎可以控制访问权限,快速处理事务,进行联机事务处理和联机数据分析的数据库对象,还用于创建数据库表,管理和保护数据的数据库对象(索引、视图、存储过程)
2、数据库引擎的主线任务
数据库引擎的主线任务,其实就是创建数据库系统的主要任务
设计: 设计创建数据库系统中各个功能所对应关系(表之间的关系)
创建: 创建数据库的表,管理和保护数据的数据库对象(索引、视图、存储过程)
部署: 为客户等 部署数据管理系统
维护: 提供日常的维护,性能的调优等。
数据库的存储引擎
1、什么是存储引擎?
存储引擎就是 存储组织数据的一种格式,通俗的来讲就是使用不同的技术对数据进行存储,有不同的存储方式,索引技巧,锁定水平等,还提供了不能的功能和能力。
2、说一下你知道的存储引擎
InnoDB、MyIsam、memory、blackhole、csv、Archive(归档)、federated、Mrg_isam
3、他们都有什么特点?
InnoDB: 是事物型的存储引擎,支持事物安全表(ACID),支持行级锁,支持外键,同时也是mysql 的默认存储引擎,InnoDB可以和其他存储引擎混合使用,他是其他基于磁盘存储引擎不能匹敌的存在,在创建数据表,默认使用主键作为唯一索引创建数据表,如果没有定义主键,那么InnoDB会给每一行数据生成一个6字节的 row ID,并将其作为主键去创建表
MyIsam:是web应用最常用的存储引擎之一,它具有较高的查询和插入效率,但是它不支持行锁和外键,在修改数据的时候,要锁定整个表,对于那些经常性修改的表,开发效率不高,
memory: 是基于内存存储的存储引擎,他将所有的数据存储到内存当中,具有很高的数据操作性能,开发效率高,但是,他正是因为存储在内存中,如果突然出现宕机、守护进程断掉,那么它所有的数据都会消失,有效率的同时也带来了很大的弊端,如果有些数据立即要用的情况,如果出现宕机等不可避免的危害,数据丢失并不会对服务造成影响就可以使用,如那些临时数据
blackhoel: 黑洞存储引擎,顾名思义,就是使用这个存储引擎,所有存入的数据都会消失,永远保持为空
vsc: 是基于csv格式数据的存储引擎,主要是对csv的数据进行操作,特点:创建数据表中强制性的每一行数据都not null ,并且不支持索引,不支持分区。因为是跟csv可以使用office直接操作,难免不了出现数据出乱的情况
数据库的隔离级别
读未提交(read uncommitted): 脏读 不可重复读 幻读
读已提交(read committed) 不可重复度 幻读
不可重复度(repeat read) 幻读
可串行化(Serializable) –
1、RC、RR级别之下怎么处理不可重复读的?
MVCC
2、RC、RR级别之下非阻塞读是如何实现的?
3、RR级别之下怎么避免幻读?
表象上: 使用快照读
使用next—key临间锁
数据库的索引
索引的分类
主键索引
普通索引
唯一索引
联合索引
全文索引
索引的存储结构
hash B+tree
索引的优点
快速查询到指定的字段和数据
索引的缺点
创建索引和维护索引非常的消耗时间
索引很多的情况下,是很消耗物理空间的
回表:
mysql默认在创建数据表时,会使用非空且唯一的键创建B+tree,一般是使用主键去创建B+tree,当数据表中给另一个非空且唯一的字段添加索引,会新开辟一个B+tree,这个新开辟的B+tree所有的叶子节点存放的是主键,当指定该字段查询数据时,会优先查询这个新B+tree,先查询到叶子节点中的主键,再使用主键回到主键B+tree树中查询到数据,这种从一个树回到主键树的查询过程,就称之为回表
索引覆盖:
在使用另一个非空且唯一的字段添加索引,创建新的B+tree,并且,在查询过程中,指定查询ID,那么,会直接从新的B+tree中查询到ID,不再回表查询,这种就是索引覆盖
索引下推:
是基于ICP:是一种优化索引查询的方式,不使用ICP的情况下,服务器发送查询指令给存储引擎,存储引擎查询到结果给服务器,由服务器进行判断数据是否符合条件,符合则返回数据,在使用ICP的时,当有指定索引的列的判断时,服务器会将这个判断的权限,下发给存储引擎,由存储引擎判定是否符合条件,符合则返回数据,减小服务器的压力,提高查询效率
联合索引:
当一个索引中,有两列或者多列的索引,就是联合索引,例如:name,age,这两个字段经常性的修改,那么就可以针对这两个字段去添加联合索引,增加选择性,提高查询速度
最左查询:
最左查询就是依赖于联合索引,当使用联合索引查询多个字段时,会优点查询最左则的一列数据,查询如果存在,才会依次往后查询,如果第一列不存在,就不会再使用这个联合索引。
前缀索引:
当我们创建索引时,难免会出现指定列的索引很大,还很长,在进行查询时,会很慢,如:小说,文章等TEXT这些,就要使用前缀索引,指定使用索引的一部分添加索引,节约索引空间,增加查询效率,但是降低索引的选择性,当优化器进行优化选择查询添加时,没有更过的选择,就只能扫描更多的数据行。但是一般来说,前缀索引的一部分就已经满足了,不会出现这种情况
聚集索引:
是InnoDB存储引擎之下的存储结构,使用B+tree的进行存储,但是它所有的叶子节点直接存放数据和索引,默认创建文件时,也只会创建两个文件,一个表文件,一个数据和索引文件,这种索引和数据存放在一起称之为聚集索引
非聚集索引:
是MyIsam存储引擎的存储结构,使用B+tree进行存储,他所有的叶子节点存储的外部空间的地址引用,当进行查询时会进行二次寻址,默认创建文件有三个,一个表头文件,一个索引文件,一个数据文件。这种称之为非聚集索引
数据库的锁
按照锁间隙
间隙锁 select * from quser where id < 5 for update 范围内加锁,其他事物不得对范围内的数据进行操作
select * from quser where name='tom' for update 如果加锁的name有很多个,就会加上间隙锁
临间锁 select * from quser where name='tom' lock in share mode;
指定行锁,如果name有很多个,那么就会范围内,在加上行锁,就是临间锁
按照锁的粒度划分
行锁 select * from quser where id=1 for update;指定某一行加锁,就是行锁
表锁 select * from quser where name='tom' for update;;
只要不是指定索引查询就会加上表锁
页锁 select * from quser limit 200 for update;
按照锁的类别划分
共享锁
又称为读锁,允许一个事务去读一行,阻止其他事务获得相同数据集的排它锁,若事务A对数据对象a加上了锁,则事务A可以读A。其他事务还可以对这个数据添加共享锁,但不能修改A,不能加排它锁,直到事务A释放锁 begin;
select * from quser where id=1 lock in share mode;
排它锁、独占锁
又称为写锁,就是说事务A使用写锁操作一条数据,阻止其他事务添加任何的锁,直到事务A操作完所有的事物,提交之后,其他事务才可以添加其他的锁 begin;
select * from quser where id=1 for update;
按照锁的使用方式划分
乐观锁:顾名思义,当一个事物修改数据时,它总是认为世界是乐观的,总以为此时并没有人去修改数据,所以,乐观锁之下,会先去进行逻辑处理,不到万不得已,不去获取锁,如果最后获取的锁与开启事物的锁字段不同,那么就不允许修改事物,事物只能回滚,
悲观锁:事物开启,它认为世界是悲观的,所以在开始逻辑处理之前,会先去获取锁,再进行事物操作,获取锁之后,其他事物,只能等待,不能对加锁的数据进行操作,这种情况,在高并发情况之下,很容易造成死锁,不好获取锁
总结:
乐观锁,锁的粒度小,不会出现死锁,使用于高并发的业务处理,适合在获取锁失败几率低的情况之下,可以提高整个业务处理的性能
悲观锁:使用于数据量小,高并发少,并且对数据的安全性有很高的要求
按照加锁的方式
自动锁
显示锁