MySQL

数据库

0、什么是索引?

索引是帮助MySQL高效获取数据的数据结构,主要是用来提高数据检索的效率,降低数据库的IO成本,同时通过索引列对数据进行排序,降低数据排序的成本,也降低了CPU的消耗。

索引的优点:

(1)使用索引可以大大加快数据的检索速度。

(2)通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

索引的缺点:

(1)创建索引和维护索引需要耗费许多时间。当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态的修改,会降低SQL执行效率。

(2)索引需要使用物理文件存储,也会耗费一定空间。

1、索引的底层数据结构了解过吗?

MySQL默认的存储引擎InnoDB采用B+树的数据结构来存储索引,选择B+树的主要原因是:第一阶数更多,路径更短;第二磁盘读写代价B+树更低,非叶子节点只存储指针,叶子节点存储数据;第三B+树便于扫库和区间查询,叶子节点是一个双向链表。

2、MySQL索引有哪些?

按照数据结构维度划分:

(1)BTree索引:是MySQL默认最常用的索引类型。只有叶子节点存储value,非叶子节点只有指针和key。存储引擎MyISAM和InnoDB实现BTree索引都是使用B+Tree,但二者实现方式不一样。InnoDB引擎中,其数据文件本身就是索引文件。相比MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按B+Tree组织的一个索引结构,树的叶子节点data域保存了完整的数据记录。

(2)哈希索引:类似键值对的形式,一次即可定位。

(3)全文索引:对文本内容进行分词,进行搜索。目前只有CHAR、VARCHAR、TEXT列上可以创建全文索引。一般不会使用,效率较低,通常使用搜索引擎如ElasticSearch代替。

按底层存储方式角度划分:

(1)聚簇索引:索引结构和数据一起存放的索引,InnoDB中的主键索引就属于聚簇索引。

(2)非聚簇索引:索引结构和数据分开存放的索引,二级索引(辅助索引)就属于非聚簇索引。

MySQL的MyISAM引擎,不管是主键还是非主键,使用的都是非聚簇索引。

按应用维度划分:

(1)主键索引:加速查询+列值唯一(不可以有NULL)+表中只有一个。

(2)普通索引:仅加速查询。

(3)唯一索引:加速查询+列值唯一(可以有NULL)。

(4)覆盖索引:一个索引包含所有需要查询的字段的值。

(5)联合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并。

(6)前缀索引:前缀索引只适用于字符串类型的数据,前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小,因为只取前几个字符。

MySQL 8.x中实现的索引新特性:

(1)隐藏索引:也称为不可见索引,不会被优化器使用,但是仍然需要维护,通常在软删除和灰度发布的场景中使用。主键不能设置为隐藏。

(2)降序索引:之前的版本支持通过desc来指定索引为降序,但实际上创建的仍然是常规的升序索引。直到MYSQL 8.x版本才开始真正支持降序索引。另外,在MySQL 8.x版本中,不再对GROUP BY语句进行隐式排序。

(3)函数索引:从MYSQL 8.0.13版本开始支持在索引中使用函数或者表达式的值,也就是在索引中可以包含函数或者表达式。

3、B树和B+树的区别?

B树是多路平衡查找树。

(1)B树的所有节点既存放键(key)也存放数据(data),而B+树只有叶子节点存放key和data,其他内节点只存放key。

(2)B树的叶子节点都是独立的,B+树的叶子节点有一条引用链指向与它相邻的叶子节点。

(3)B树的检索过程相当于对范围内的每个节点的关键字做二分查找,可能还没有到达叶子节点,检索就结束了。而B+树的检索效率就很稳定了,任何查找都是从跟节点到叶子节点的过程,叶子节点的顺序检索很明显。

(4)在B树中进行范围查询时,首先找到要查找的下限,然后对B树进行中序遍历,直到找到查找的上限;而B+树的范围查询,只需要对链表进行遍历即可。

4、聚簇索引和非聚簇索引的详细介绍?

聚簇索引主要是指数据与索引放到一起存储,B+树的叶子节点保存了整行数据,有且只有一个,一般情况下主键是作为聚簇索引的。

非聚簇索引指的是数据与索引分开存储,B+树的叶子节点保存对应的主键,可以有多个,一般我们自己定义的索引都是非聚簇索引。

聚簇索引即索引结构和数据一起存放的索引,并不是一种单独的索引类型。InnoDB中的主键索引就属于聚簇索引。在MySQL中,InnoDB引擎的表的.ibd文件就包含了该表的索引和数据,对于InnoDB引擎表来说,该表的索引(B+树)的每个非叶子节点存储索引,叶子节点存储索引和索引对应的数据。

非聚簇索引的叶子节点并不一定存放数据的指针,因为二级索引的叶子节点就存放的是主键,根据主键再回表查数据。

B+树中,如果为聚簇索引,叶子节点的data域存放数据;如果是非聚簇索引,data将存放指向数据的指针。

聚簇索引的优点:(1)查询速度非常快:聚簇索引的查询速度非常的快,因为整个B+树本身就是一颗多叉平衡树,叶子节点也都是有序的,定位到索引的节点,就相当于定位到了数据。相比于非聚簇索引,聚簇索引少了一读取数据的IO操作。(2)支持排序查找和范围查找优化:聚簇索引对于主键的排序查找和范围查找速度非常快。

缺点:(1)依赖于有序的数据:因为B+树是多路平衡树,如果索引的数据不是有序的,那么就需要在插入时排序,如果数据是整型还好,否则类似于字符串或UUID这种又长又难比较的数据,插入或查找的速度肯定比较慢。(2)更新代价大:如果索引列的数据被修改时,那么对应的索引也将会被修改,而且聚簇索引的叶子节点还存放着数据,修改代价肯定是较大的,所以对于主键索引来说,主键一般都是不可被修改的。

非聚簇索引的优点:(1)更新代价比聚簇索引要小。非聚簇索引的叶子节点是不存放数据的。

缺点:(1)依赖于有序的数据:跟聚簇索引一样,非聚簇索引也依赖于有序的数据。(2)可能会二次查询(回表):当查到索引对应的指针或主键后,可能还需要根据指针或主键再到数据文件或表中查询。

.myd文件包含表的数据,.myi文件包含表的索引。【MyISAM】

5、什么是回表查询呢?

回表查询与聚簇索引和非聚簇索引是有关系的,回表就是通过二级索引找到对应的主键值,然后再通过主键值找到聚簇索引中所对应的整行数据,这个过程就是回表。

6、哈希索引和B+树索引?

B+树索引:

(1)基本思想:B+树索引是一种多路平衡查找树,它将索引键按顺序存储在树的叶子节点中,并通过内部节点的索引来快速定位到叶子节点。

(2)优点:支持范围查询:B+树索引能够有效支持范围查询,例如大于、小于等条件。支持模糊查询:B+树索引对模糊查询也有良好的支持。适用于范围查询频繁的情况:如果查询中包含了范围查询,B+树索引通常更优。

(3)缺点:相对较大的内存开销:B+树索引相对于哈希索引需要占用更多的内存。查找效率相对于哈希索引略低:B+树索引的查找复杂度通常是对数级别的,即O(log n)。

(4)适用范围:适用于范围查询较多的场景,如区间查询、排序等。适用于数据分布较为平均的情况。

哈希索引:

(1)基本思想:哈希索引是通过将索引键的哈希值映射到一个固定大小的散列表中,快速定位到对应的数据块,从而实现快速检索。

(2)优点:快速查找:在理想情况下,哈希索引的查找效率是常数级别的,即O(1)。适用于等值查询:对于等值查询(如通过主键查找)、连接等操作,哈希索引效果显著。

(3)缺点:不支持范围查询:哈希索引不支持范围查询,例如大于、小于等条件无法直接利用哈希索引进行优化。不适用于模糊查询:对于模糊查询,哈希索引也不起作用,因为哈希函数将相似的键映射到不同的桶中。

(4)适用场景:适用于等值查询较多的场景,如主键查询。适用于内存较小的情况,因为哈希索引通常比B+树索引占用更少的内存。

7、mysql超大分页处理?

进行limit分页查询,需要对数据进行排序,越往后,分页查询的效率越低。

优化思路就是创建覆盖索引,通过覆盖索引加子查询形式进行优化。

8、索引下推是什么?

索引下推是MySQL 5.6版本中提供的一项索引优化功能,可以在非聚簇索引遍历过程中,对索引中包含的字段先做判断,过滤掉不符合条件的记录,减少回表次数。

9、索引创建的规则?

(1)被频繁查询的字段。

(2)被作为条件查询的字段。

(3)频繁需要排序的字段。

频繁需要分组的字段。

(4)字符串类型的字段使用前缀索引代替普通索引。

(5)不为NULL的字段。

(6)被经常频繁用于连接的字段。

(7)尽可能的考虑建立联合索引而不是单列索引。

(8)限制每张表上的索引数量。

(9)注意避免冗余索引,冗余索引指的是索引的功能相同,应该尽量扩展已有的索引而不是创建新索引。

(10)删除长期未使用的索引。MySQL 5.7可以通过sys库的schema_unused_indexes视图来查询哪些索引从未被使用。

10、索引失效的情况?

(1)<>不等于会导致索引失效。

(2)模糊查询中,使用like关键字,like查询以%开头就会失效,以%结尾不会失效;

(3)不符合最左匹配原则,索引的最左边那个条件必须有;

(4)索引列进行了类型转换;

(5)where后使用or导致索引失效;

(6)对索引列进行了计算或使用了函数;

(7)如果使用了复合索引,查询中包含范围条件,右侧的条件索引也会失效。

11、如何分析语句是否走索引查询?

可以使用EXPLAIN命令来分析SQL的执行计划,这样就知道语句是否命中索引了。执行计划是指一条SQL语句在经过MySQL查询优化器的优化会后,具体的执行方式。

EXPLAIN并不会真的去执行相关的语句,而是通过查询优化器对语句进行分析,找出最优的查询方案,并显示对应的信息。

12、SQL语句执行很慢,如何分析?

(1)通过keykey_len检查是否命中了索引。

(2)通过type字段查看sql是否有进一步的优化空间。

(3)通过extra建议判断,是否出现了回表的情况(添加索引或修改返回字段)。

13、sql优化?

(1)表的设计优化,数据类型选择根据需求来。

(2)索引优化(索引创建原则)。

(3)sql语句优化(不使用select *,避免索引失效,聚合查询多用union all(union会多一次过滤),表关联使用inner join,不使用left join,right join)。

(4)采用主从复制,读写分离的模式,让数据库的写入,不影响查询的效率。

(5)分库分表。

14、事务的特性?

事务是一组操作的集合,不可分割的工作单位。ACID

(1)原子性:事务是不可分割的最小操作单元,要么全部成功,要么全部失败。

(2)一致性:事务完成时,必须使所有数据保持一致状态。

(3)隔离性:保证事务在不受外部并发操作影响的独立环境运行。

(4)持久性:事务一旦提交或回滚,对数据库数据的改变是永久的。

15、事务一致性是通过什么实现的?

MySQL会使用事务日志进行恢复,将事务重新应用到数据库中,从而保证事务的一致性。回滚日志记录了事务对数据的修改情况,它允许在事务回滚时恢复数据到之前的状态。

16、事务隔离性是通过什么实现的?

MySQL通过MVCC实现了事务的隔离性,它通过在每行数据上保留多个版本来实现非阻塞的读操作。

MySQL使用锁来实现事务的隔离性,保证同时运行的事务之间相不干扰。不同的隔离级别会采用不同的锁策略。

17、并发事务带来的问题,怎么解决这些问题?

脏读:一个事务读到另一个事务还没有提交的数据。

不可重复读:一个事务先后读取同一条记录,两次读取的数据不同。

幻读:一个事务按照条件查询数据时,没有对应的数据行,插入数据时,又发现这行数据已经存在。

解决方案:对事务进行隔离。

18、MySQL的隔离级别?

(1)读取未提交内容:最低的隔离级别,允许一个事务读取另一个未提交事务所做的修改,可能导致脏读问题。

(2)读取已提交内容:保证一个事务只能读取已经提交的数据,避免了脏读问题,但可能导致不可重复读问题。

(3)可重复读(默认的):保证一个事务在整个事务过程中读取的数据保持一致,即使其他事务对数据进行了修改。避免了不可重复读问题,但可能会导致幻读问题。

(4)序列化:最高的隔离级别,提供最强的事务隔离。保证同时执行的事务之间不会出现脏读、不可重复读和幻读问题。通过锁机制来实现,可能会导致并发性能下降。

事务隔离级别越高,数据越安全,但是性能越低。

19、解决幻读的方法?

核心思想就是一个事务在操作某张表数据的时候,另外一个事务不允许新增或者删除这张表中的数据。具体地:

(1)将事务隔离级别调整为序列化。

(2)在可重复读的事务级别下,给事务操作的这张表添加表锁。

(3)在可重复读的事务级别下,给事务操作的这张表添加Next-Key Lock(Record Lock+Gap Lock)。

20、InnoDB的可重复读?

但是InnoDB实现的可重复读隔离级别是可以解决幻读问题发生的,有两种情况:

(1)快照读:由MVCC机制来保证不出现幻读。

(2)当前读:使用Next-Key Lock进行加锁来保证不出现幻读,Next-Key Lock是行锁和间隙锁的结合,行锁只能锁住已经存在的行,为了避免插入新行,需要依赖间隙锁。

21、InnoDB在分布式事务下采用序列化隔离级别?

InnoDB存储引擎提供了对XA事务的支持,并通过XA事务来支持分布式事务的实现。

分布式事务指的是允许多个独立的事务资源参与到一个全局的事务中。

22、MySQL的存储引擎?

MySQL 5.5.5之前,MyISAM是MySQL的默认存储引擎。5.5.5版本后,InnoDB是Mysql的默认存储引擎。

23、MySQL存储引擎架构了解吗?

MySQL存储引擎采用的是插件式架构,支持多种存储引擎,可以为不同的数据库表设置不同的存储引擎以适应不同场景的需要。存储引擎是基于表的,而不是数据库。

24、MyISAM和InnoDB的区别?

(1)MyISAM只支持表级别的锁粒度,而InnoDB支持行级别的锁粒度。

(2)MyISAM不提供事务支持。InnoDB提供事务支持,实现了SQL标准定义了四个隔离级别。

(3)MyISAM不支持外键,而InnoDB支持。

(4)MyISAM不支持MVCC,而InnoDB支持。

(5)MyISAM不支持数据库异常崩溃后的安全恢复,而InnoDB支持。

(6)虽然MyISAM引擎和InnoDB都是使用B+Tree作为索引结构,但是两者的实现方式不太一样。InnoDB引擎中,其数据文件本身就是索引文件。相比MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按B+Tree组织的一个索引结构,树的叶子节点data域保存了完整的数据记录。

25、InnoDB对MVCC的实现?

MVCC多版本并发控制,指维护一个数据的多个版本,使得读写操作没有冲突。

InnoDB通过数据行的DB_TRX_ID和Read View来判断数据的可见性,如不可见,则通过数据行的DB_ROLL_PTR找到undo log中的历史版本。每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建Read View之前已经提交的修改和该事务本身做的修改。

其实现依赖于数据库记录中的隐式字段,read view,undo log。

(1)隐藏字段。(InnoDB存储引擎为每行数据添加了三个隐藏字段)

  • DB_TRX_ID(事务id、6字节):表示最后一次插入或更新该行的事务id,自增的。

  • DB_ROLL_PTR(7字节):回滚指针,指向该行的undo_log。如果该行未被更新,则为空。

  • DB_ROW_ID(6字节):如果没有设置主键且该表没有唯一非空索引时,InnoDB会使用该id来生成聚簇索引。

(2)ReadView。(解决一个事务查询选择版本的问题,快照读SQL执行是MVCC提取数据的依据,记录并维护系统当前活跃的事务id。)

  • 快照读:简单的select就是快照读,读取的是记录数据的可见版本。

  • 当前读:读取记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。

RC(读取已提交)级别下,事务每一次执行快照读时生成readview。

RR(可重读)级别下,仅在事务中第一次执行快照读时生成readview,然后复用readview。

(3)uodo log(回滚日志)。

  • 回滚日志:存储老版本数据。

  • 版本链:不同事务或者相同事务对同一条记录进行修改,该记录的undo log生成一条记录版本链表,链表的头部是最新的旧记录,尾部是最早的旧记录。

26、Mysql锁有哪些,如何理解?

按锁粒度分类:

(1)行锁:锁某行数据,锁粒度最小,并发度高,针对索引字段加的锁,只针对当前操作的行记录进行加锁。行级锁和存储引擎有关,是在存储引擎层面实现的。但是加锁的开销大,加锁慢,会出现死锁。

(2)表锁:锁整张表,锁粒度最大,并发度低,针对非索引字段加的锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。表级锁和存储引擎无关,MyISAM和InnoDB引擎都支持表级锁。

(3)间隙锁:锁的是一个区间。

还可以分为:

(1)共享锁:也就是读锁,一个事务给某行数据加了读锁,其他事务也可以读,但是不能写;

(2)排它锁,也就是写锁,一个事务给某行数据加了写锁,其他事务不能读,也不能写。

还可以分为:

(1)乐观锁:并不会真正的去锁某行记录,而是通过一个版本号来实现的。

(2)悲观锁:上面锁的行锁、表锁等都是悲观锁。

在事务的隔离级别实现中,就需要锁来解决幻读。

27、行级锁的使用有什么注意事项?

InnoDB的行锁是针对索引字段加的锁,表级锁是针对非索引字段加的锁。当我们执行UPDATE、DELETE语句时,如果WHERE条件中字段没有命中唯一索引或者索引失效的话,就会导致扫描全表中的所有行记录进行加锁。

28、InnoDB有哪几类型锁?

InnoDB行锁是通过对索引数据页上的记录加锁实现的,支持三种行锁定方式:

(1)记录锁(Record Lock):属于单个行记录上的锁。

(2)间隙锁(Gap Lock):锁定一个范围,不包括记录本身。

(3)临键锁(Next-Key Lock):Record Lock + Gap Lock,锁定一个范围,包含记录本身,主要目的是为了解决幻读问题。记录锁只能锁住已经存在的记录,为了避免插入新纪录,需要依赖间隙锁。

29、意向锁有什么作用?

意向锁是表级锁,有两种:

(1)意向共享锁:事务有意向对表中的某些记录加共享锁(S锁),加共享锁前必须先取得该表的IS锁。

(2)意向排他锁:事务有意向对表中的某些记录加排他锁(X锁),加排他锁前必须先取得该表的IX锁。

意向锁是由数据引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享/排他锁之前,InnoDB会先获取该数据行所在数据表的对应意向锁。

30、自增锁有了解吗?

如果一个事务正在插入数据到自增列的表时,会先获取自增锁,拿不到就可能会被阻塞住。这里的阻塞行为只是自增锁行为的其中一种,可以理解为自增锁就是一个接口,其具体的实现有多种。

具体的配置项为:innodb_autoinc_lock_mode,可以选择的值如下:

0—传统模式;1—连续模式;2—交错模式。

交错模式下,所有的INSERT-LIKE都不使用表级锁,使用的是轻量级互斥锁实现,多条插入语句可以并发执行,速度更快,扩展性也更好。

如果MySQL数据库有主从同步需求并且Binlog存储格式为Statement的话,不要将InnoDB自增锁模式设置为交叉模式,不然会有数据不一致性问题。这是因为并发情况下插入语句的执行顺序就无法得到保障。

31、锁升级过程,可以降级吗?

(1)悲观锁升级: 在某些情况下,可以将悲观共享锁升级为悲观排他锁。例如,在读多写少的场景中,当需要修改数据时,可以将共享锁升级为排他锁,以防止其他线程的读写操作干扰。

(2)乐观锁升级: 乐观锁一般不涉及锁升级,因为乐观锁的核心思想是通过版本号或时间戳等机制来避免锁竞争,而不需要进行锁的升级。

锁降级的支持取决于具体的锁实现和编程语言。在某些情况下,锁降级是可能的,但在其他情况下可能会更加复杂或不可行。一般来说,锁降级需要确保在释放高级别锁之前,已经获得低级别锁,以避免数据不一致或并发问题。

32、数据库如何降低死锁?

(1)降低事务的隔离级别。

降低事务的隔离级别可以减少死锁的发生,因为事务的隔离级别越高,锁的粒度就越大,这会增加死锁的概率。但是,等级太低可能会引起脏读、不可重复读和幻读等问题,需要根据实际情况权衡。

(2)减少事务并发度。

减少事务并发度也可以减少死锁的发生。当存在大量并发事务时,会增加死锁的概率。可以通过调整业务流程或者更改代码实现。

  • 优化SQL语句和索引。

    优化SQL语句和索引可以减少对同一数据行的竞争,从而降低死锁的概率。可以通过合理设计索引、使用批量更新或者延迟加载等方式来优化SQL语句。

  • 使用数据库的死锁检测和超时机制。

    大多数数据库会提供死锁检测和超时机制,可以使用这些机制来避免或解决死锁问题。当发现死锁时,数据库会自动回滚其中一个事务,释放资源,避免了死锁的进一步扩大。而超时机制则可以在一定时间内主动结束事务,释放资源,避免死锁的长时间持续,从而提高数据库的并发性能。

33、MySQL中三大日志?

(1)binlog二进制日志(归档日志):是逻辑日志,记录内容是语句的原始逻辑,类似于“给ID=2这一行的c字段加1”,属于MySQL的Server层。保证数据的一致性。会记录所有涉及更新数据的逻辑操作,并且是顺序写。

binlog日志有三种格式,可以通过binlog_format参数指定,分别是:statement(记录了SQL语句原文)、row(还包含操作的具体数据)、mixed()。row格式记录的内容看不到详细信息,要通过mysqlbinlog工具解析出来。

(2)redolog重做日志(事务日志):是物理日志,记录内容是“在某个数据页上做了什么修改”,属于InnoDB存储引擎。保证事务的持久性。

(3)undolog回滚日志:保证事务的原子性。记录了事务的撤销操作,它用于在事务回滚时恢复数据到事务开始之前的状态。当事务执行过程中需要回滚或发生错误时,回滚日志被用来还原事务对数据所做的改变。

34、redo log和undo log的区别?

redo log日志记录的是数据页的物理变化,服务宕机可以用来同步数据,而undo log主要记录的是逻辑日志,当事务回滚时,通过逆操作来恢复原来的数据。

redo log保证了数据的持久性,undo log保证了事务的原子性和隔离性。

 

redo log:记录的是事务提交时数据页的物理修改,用来实现事务的持久性

组成:重做日志缓冲和重做日志文件,前者在内存中,后者在磁盘中。

undo log:回滚日志,用于记录数据被修改前的信息,作用包括两个:提供回滚MVCC(多版本并发控制)可以实现事务的一致性和原子性

35、MySQL主从复制原理?

MySQL主从复制的核心就是二进制日志

(1)主库将数据库中数据的变化写入到binlog。

(2)从库连接主库。

(3)从库会创建一个I/O线程向主库请求更新的binlog。

(4)主库会创建一个binlog dump线程来发送binlog ,从库中的I/O线程负责接收。

(5)从库的I/O线程将接收的binlog写入到relay log中。

(6)从库的SQL线程读取relay log同步数据本地(也就是再执行一遍 SQL )。

36、如何实现Mysql读写分离?

(1)部署多台数据库,选择其中的一台作为主数据库,其他的一台或者多台作为从数据库。

(2)保证主数据库和从数据库之间的数据是实时同步的,这个过程也就是我们常说的主从复制

(3)系统将写请求交给主数据库处理,读请求交给从数据库处理。

在项目中,常用的方式有两种:

(1)代理方式:可以在应用和数据中间加了一个代理层。应用程序所有的数据请求都交给代理层处理,代理层负责分离读写请求,将它们路由到对应的数据库中。提供类似功能的中间件有 MySQL RouterAtlas(基于 MySQL Proxy)、MaxScaleMyCat

(2)组件方式:通过引入第三方组件来帮助我们读写请求。可以使用 sharding-jdbc ,直接引入jar包即可使用,非常方便。同时,也节省了很多运维的成本。

37、主从一致性问题?

(1)强制将读请求路由到主库处理。

既然从库的数据过期了,那就可以直接从主库读取!这种方案虽然会增加主库的压力,但是,实现起来比较简单。

比如 Sharding-JDBC就是采用的这种方案。通过使用Sharding-JDBC的 HintManager 分片键值管理器,我们可以强制使用主库。

在这种方案中,可以将那些必须获取最新数据的读请求都交给主库处理。

(2)延迟读取。

比如主从同步延迟0.5s,那就1s之后再读取数据。

对于一些对数据比较敏感的场景,可以在完成写请求之后,避免立即进行请求操作。比如你支付成功之后,跳转到一个支付成功的页面,当你点击返回之后才返回自己的账户。

38、分库分表?

解决存储压力。

垂直分库:根据业务进行拆分,高并发下提高磁盘IO和网络连接数;实现微服务。

垂直分表:冷热数据分离,多表互不影响。

水平分库:一个库的数据拆分到多库,解决海量数据存储和高并发的问题。

水平分表:解决单表存储和性能问题。

  • 引入分库分表之后,需要系统解决事务、分布式id、无法join操作问题。

  • ShardingSphere的功能完善,除了支持读写分离和分库分表,还提供分布式事务、数据库治理等功能。另外,ShardingSphere的生态体系完善,文档完善,更新和发布比较频繁。

39、三大范式?

  1. 第一范式(1NF):确保每个数据库表中的每个列都包含原子值,即不可再分。这意味着每个单元格只能包含一个值,不允许多个值的集合、数组或嵌套结构。这有助于减少数据冗余。

  2. 第二范式(2NF):在满足第一范式的基础上,要求表中的每个非主键列都完全依赖于主键,而不是依赖于主键的一部分。这有助于消除部分依赖,确保数据的一致性和完整性。

  3. 第三范式(3NF):在满足第二范式的基础上,要求表中的每个非主键列都不依赖于其他非主键列。这有助于消除传递依赖,确保数据更新异常的减少。

40、动态sql?

可以根据特定的情况动态地生成不同的SQL语句,从而实现灵活的查询。在构建动态SQL时,应该谨慎处理用户输入,避免直接拼接用户输入到SQL语句中。

可能存在SQL注入问题。防止SQL注入的方法有:

(1)使用参数化查询或预编译语句。使用参数化查询可以防止用户输入的数据被解释为SQL代码,不要直接将用户输入拼接到SQL查询中。

(2)限制数据库用户权限。给应用程序连接数据库的用户分配最小必要的权限,避免使用具有过高权限的用户。

(3)输入验证。在应用程序层面对用户输入进行验证,确保他们符合预期的格式和范围。

(4)转义特殊字符。

(5)使用ORM(对象关系映射):ORM框架通常会提供内建的防护机制,可以有效防止SQL注入。

41、MySQL的分片算法?

分片算法主要解决了数据被水平分片之后,数据究竟该存放在哪个表的问题。

(1)哈希分片:求指定key(比如 id) 的哈希,然后根据哈希值确定数据应被放置在哪个表中。哈希分片比较适合随机读写的场景,不太适合经常需要范围查询的场景。

(2)范围分片:按照特性的范围区间(比如时间区间、ID 区间)来分配数据,比如将 id1~299999 的记录分到第一个库, 300000~599999 的分到第二个库。范围分片适合需要经常进行范围查找的场景,不太适合随机读写的场景(数据未被分散,容易出现热点数据的问题)。

(3)地理位置分片:很多NewSQL数据库都支持地理位置分片算法,也就是根据地理位置(如城市、地域)来分配数据。

(4)融合算法:灵活组合多种分片算法,比如将哈希分片和范围分片组合。

42、MySQL的对象有哪些?

数据库、表、视图(视图是一个虚拟表,其内容是一个查询定义,可以简化复杂的查询操作,也可以用于控制用户对数据的访问权限)、函数、索引。

43、#{}和${}的区别是什么?

#{}是预编译处理,是占位符,Mybatis在处理#{}时,会将sql中的#{}替换为?号,再调用PreparedStatement来赋值。使用#{}可以有效的防止SQL注入,提高系统安全性。

${}是字符串替换、是拼接符。Mybatis在处理${}时,会将sql中的${}替换成变量的值,再调用Statement来赋值。

44、Mybatis的批处理?

(1)首先编写Mapper文件,在Mapper文件中编写SQL语句,需要使用foreach标签来循环执行批处理的SQL。

(2)然后编写DAO接口方法,在DAO接口中定义批处理的方法,方法的参数应该是一个List,其中包含了需要批处理的对象。

(3)在Mybatis的配置文件中,需要添加批处理选项。

(4)在代码中调用批处理方法,并传入需要批处理的数据列表。

批处理通常用于批量插入、更新等操作,可以有效地减少数据库访问次数,提升性能。

45、MyBatis怎么防止sql注入?

(1)使用参数绑定:可以确保用户输入的数据不会直接拼接到SQL查询中,而是通过参数的方式传递给数据库。

应该用#{}。

(2)不要使用字符串拼接来构建SQL查询。

String sql = "SELECT * FROM users WHERE username = '" + userInput + "'';

(3)动态SQL标签,可以根据条件动态生成SQL查询语句。这样可以避免不必要的拼接。

(4)使用预编译语句:如果在Java代码中直接操作数据库,确保使用预编译语句。这可以防止直接在SQL查询中插入恶意代码。

(5)在接受用户输入之前,进行输入验证和过滤,以确保输入符合预期格式和范围。

(6)避免直接将用户输入传递给动态SQL,而是先进行验证和过滤,然后再将参数传递给MyBatis。

 

 

posted @ 2024-06-28 14:46  守漠待花开  阅读(50)  评论(0)    收藏  举报