Review:数据库

https://yanglinwei.blog.csdn.net/article/details/103972288

MySQL主从复制:通过主从复制可以实现数据备份、故障转移、MySQL集群、高可用、读写分离等。原理如下:

  1. 从库生成两个线程,一个I/O线程,一个SQL线程
  2. I/O线程去请求主库的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中;
  3. 主库会生成一个 log dump 线程,用来给从库 i/o线程传binlog;
  4. SQL 线程会读取relay log文件中的日志,并解析成具体操作,来实现主从的操作一致,而最终数据一致;

在这里插入图片描述


MyCat:MyCat主要是通过对SQL的拦截,然后经过一定规则的分片解析、路由分析、读写分离分析、缓存分析等,然后将SQL发给后端真实的数据块,并将返回的结果做适当处理返回给客户端。

在这里插入图片描述


MyCat安装与配置:主要配置解压包的schema.xml文件

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
    <!-- TESTDB1 是mycat的逻辑库名称,链接需要用的 -->
    <schema name="mycat_testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
        <!-- database 是MySQL数据库的库名 -->
    <dataNode name="dn1" dataHost="localhost1" database="test" />
    <!--
    dataNode节点中各属性说明:
    name:指定逻辑数据节点名称;
    dataHost:指定逻辑数据节点物理主机节点名称;
    database:指定物理主机节点上。如果一个节点上有多个库,可使用表达式db$0-99,     表示指定0-99这100个数据库;

    dataHost 节点中各属性说明:
        name:物理主机节点名称;
        maxCon:指定物理主机服务最大支持1000个连接;
        minCon:指定物理主机服务最小保持10个连接;
        writeType:指定写入类型;
            0,只在writeHost节点写入;
            1,在所有节点都写入。慎重开启,多节点写入顺序为默认写入根据配置顺序,第一个挂掉切换另一个;
        dbType:指定数据库类型;
        dbDriver:指定数据库驱动;
        balance:指定物理主机服务的负载模式。
            0,不开启读写分离机制;
            1,全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡;
            2,所有的readHost与writeHost都参与select语句的负载均衡,也就是说,当系统的写操作压力不大的情况下,所有主机都可以承担负载均衡;
-->
    <dataHost name="localhost1" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <!-- 可以配置多个主从 -->
        <writeHost host="hostM1" url="192.168.162.132:3306" user="root" password="123456">
            <!-- 可以配置多个从库 -->
            <readHost host="hostS2" url="192.168.162.133:3306" user="root" password="123456" />
        </writeHost>
    </dataHost>
</mycat:schema>

数据库分表分库原则:遵循 垂直拆分水平拆分

  • 垂直拆分:根据不同的业务,分为不同的数据库,比如会员数据库、订单数据库、支付数据库等,垂直拆分在大型电商系统中用的非常常见。缺点是:部分业务表无法join,只能通过接口方式解决,提高了系统复杂度。
  • 水平拆分:把同一个表拆到不同的数据库中。可以将数据的水平切分理解为是按照数据行的切分,就是将表中 的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中,主要有分表,分库两种模式。水平切分提高了系统的稳定性跟负载能力,但是跨库join性能较差。比如:按时间、哈希、业务规则分表。

MyCat 10种水平分片策略

  • 求模算法:根据id进行十进制求摸运算,运算结果为分区索引,跟ES集群非常相似。
  • 分片枚举:比如按照省份或区县来做保存
  • 范围约定
  • 日期指定
  • 固定分片hash算法
  • 通配取模
  • ASCII码求模通配
  • 编程指定
  • 字符串拆分hash解析

Sharding-Jdbc:提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如Java同构、异构语言、容器、云原生等各种多样化的应用场景。应用场景:

  • 数据库读写分离
  • 数据库分表分库

SJdbc与MyCat的区别

  • MyCat是一个基于第三方应用中间件数据库代理框架,客户端所有的jdbc请求都必须要先交给MyCat,再有MyCat转发到具体的真实服务器中。
  • Sharding-Jdbc是一个Jar形式,在本地应用层重写Jdbc原生的方法,实现数据库分片形式。
  • MyCat属于服务器端数据库中间件,而Sharding-Jdbc是一个本地数据库中间件框架。

配置如下:

server:
  port: 9002
mybatis-plus:
#  mapper-locations: classpath*:/mapper/*.xml
  global-config:
    db-config:
      column-underline: true
#shardingjdbc配置      
sharding:
  jdbc:
    data-sources:
     ###配置第一个从数据库
      ds_slave_0:
        password: root
        jdbc-url: jdbc:mysql://192.168.212.203:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true
        driver-class-name: com.mysql.jdbc.Driver
        username: root
      ###主数据库配置  
      ds_master:
        password: root
        jdbc-url: jdbc:mysql://192.168.212.202:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true
        driver-class-name: com.mysql.jdbc.Driver
        username: root
    ###配置读写分离    
    master-slave-rule:
    ###配置从库选择策略,提供轮询与随机,这里选择用轮询
      load-balance-algorithm-type: round_robin
      ####指定从数据库
      slave-data-source-names: ds_slave_0
      name: ds_ms
      ####指定主数据库
      master-data-source-name: ds_master

数据库索引:是一种数据结构,用于提高数据库表的检索速度和查询性能。索引是数据库中的一种数据结构,类似于书籍的目录,它提供了一种快速访问表中特定行的方法。通过创建索引,数据库系统可以更有效地执行查询,减少数据扫描的时间,从而加快检索和查询操作。

默认数据与索引文件位置:/var/lib/mysql


索引实现原理

  • hash算法:据关键码值(Key value)而直接进行访问的数据结构,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。缺点是不能进行范围查找。
  • 平衡二叉树算法:它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值(平衡因子 ) 不超过1。 也就是说AVL树每个节点的平衡因子只可能是-1、0和1(左子树高度减去右子树高度)。优点是平衡二叉树算法基本与二叉树查询相同,效率比较高。缺点是插入操作需要旋转,支持范围查询。

在这里插入图片描述

  • 数据结构B树:B树(B-tree) 是一种树状数据结构,它能够存储数据、对其进行排序并允许以O(log n)的时间复杂度运行进行查找、顺序读取、插入和删除的数据结构。B树,概括来说是一个节点可以拥有多于2个子节点的二叉查找树。与自平衡二叉查找树不同,B-树为系统最优化大块数据的读和写操作。B-tree算法减少定位记录时所经历的中间过程,从而加快存取速度。普遍运用在数据库和文件系统

在这里插入图片描述

  • 数据结构B+树:B+树相比B树,新增叶子节点与非叶子节点关系,叶子节点中包含了key和value,非叶子节点中只是包含了key,不包含value。所有相邻的叶子节点包含非叶子节点,使用链表进行结合,有一定顺序排序,从而范围查询效率非常高。

在这里插入图片描述


MyISAM引擎(读多写少,不支持事务):使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。使用表级锁定。不支持事务。

在这里插入图片描述


**InnoDB引擎(推荐,写多读少场景,支持事务):**也使用B+Tree作为索引结构,将数据和索引都存储在同一个表空间中。这种存储结构使得InnoDB在处理大量写操作和并发事务时表现得更为优越。使用行级锁定,支持事务。


MySQL优化方案

  • 索引优化
  • 慢查询优化:开启慢查询、查询慢查询限制时间(slow_query_log)
  • 表优化

explain命令:在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决

在这里插入图片描述


联合索引左前缀原则:指索引的最左匹配原则。在MySQL中,如果你创建了一个多列索引,查询只能充分利用索引的最左边的列。

举例:

-- 创建了一个复合索引(多列索引)
CREATE INDEX idx_example ON your_table (col1, col2, col3);

-- 索引的最左边的列是col1
-- 以下查询可以使用索引
SELECT * FROM your_table WHERE col1 = 'some_value';

-- 以下查询不能充分利用索引,因为没有涉及到索引的最左边的列
SELECT * FROM your_table WHERE col2 = 'some_value';

因为MySQL在使用索引时,会从索引的最左边开始匹配,并且只有当查询条件涉及到索引的最左边的列时,MySQL才能够充分利用这个索引。


**B+树能够存放多少字节数据:**主要考虑的是B+树的叶子节点能够存储多少数据。B+树的叶子节点包含了实际的索引数据,而非叶子节点只包含索引键值用于导航。

在这里插入图片描述


事务传播机制:定义了在一个事务中嵌套调用其他事务时,事务的行为和传播规则。常见的事务传播行为包括:

  1. REQUIRED(默认):关键词:必须,表示如果当前存在事务,那么新的操作必须在该事务中进行;如果当前没有事务,将创建一个新的事务。
  2. REQUIRES_NEW需要新的,表示无论当前是否存在事务,都将创建一个新的事务。
  3. NESTED:嵌套,表示在当前事务的嵌套事务中执行。
  4. SUPPORTS:支持,表示如果当前存在事务,就加入该事务;如果没有事务,以非事务方式执行。
  5. NOT_SUPPORTED:不支持,表示以非事务方式执行,如果当前存在事务,将挂起该事务。
  6. MANDATORY:强制,表示如果当前存在事务,就加入该事务;如果没有事务,则抛出异常。
  7. NEVER:从不,表示以非事务方式执行,如果当前存在事务,将抛出异常。
  8. TIMEOUT:超时,表示以相对时间为基准,如果事务在指定时间内没有完成,就回滚事务。

事务隔离级别

  1. **READ UNCOMMITTED(未提交读):**事务可以读取其他事务尚未提交的数据,可能导致脏读、不可重复读和幻读问题。
  2. **READ COMMITTED(已提交读):**特点:事务只能读取其他事务已经提交的数据,解决了脏读问题,但仍可能有不可重复读和幻读问题。
  3. **REPEATABLE READ(可重复读):**在同一事务中多次读取相同记录时,结果是一致的。解决了脏读和不可重复读问题,但仍可能有幻读问题。
  4. **SERIALIZABLE(串行化):**最高的隔离级别,通过对数据进行加锁,解决了脏读、不可重复读和幻读的所有问题。但也可能降低并发性能。
  5. **READ SNAPSHOT(快照读):**事务可以读取一个在事务开始时快照中存在的数据版本,适用于某些数据库系统的特殊实现。事务读取在事务开始时的快照数据,而不受其他事务的影响,避免了脏读、不可重复读和幻读问题。

脏读、不可重复读和幻读

  1. 脏读(读写了未提交的):

    • 定义: 当一个事务读取了另一个事务未提交的数据时,就发生了脏读。
    • 场景: 如果事务A修改了一行数据,但尚未提交,此时事务B读取了这个未提交的数据,就可能导致脏读。
  2. 不可重复读(读提交之后的):

    • 定义: 当一个事务多次读取同一行数据,但在这个过程中另一个事务对该行数据进行了修改并提交,导致事务A读取到不同的数据,就发生了不可重复读。
    • 场景: 如果事务A在读取某一行数据后,事务B修改并提交了这一行数据,此时事务A再次读取同一行数据,就可能得到与之前不同的结果。
  3. 幻读(读一批提交之后的数据):

    • 定义: 当一个事务多次查询某个范围的数据,但在这个过程中另一个事务插入或删除了符合这个范围的数据,导致事务A得到不同的结果,就发生了幻读。
    • 场景: 如果事务A查询了一个表中的一批数据,而此时事务B插入了一条符合查询条件的新数据,再次查询的结果中会包含这条新插入的数据,就可能发生幻读。

    FOR UPDATE :是一种用于在事务中锁定所选行的语句。当你在一个事务中执行 SELECT 查询时,如果你希望防止其他事务修改这些数据,可以使用 FOR UPDATE。这会在选定的行上设置共享锁,其他事务如果尝试在这些行上执行更新、删除或添加新行的操作,会被阻塞,直到持有锁的事务释放锁。

猜你喜欢

转载自blog.csdn.net/qq_20042935/article/details/134660747
今日推荐