Mysql基础

Linux安装mysql8.0

下载安装包

https://downloads.mysql.com/archives/community/

从官网下载.tar.gz或.rpm包,上传到服务器解压缩

1
tar -xvf mysql-8.0.26-1.el7.x86_64.rpm-bundle.tar 

安装rpm包

这里是跟着黑马下载的rpm包使用rpm来安装发现rpm包缺少公钥并且明明安装openssl库却显示缺少库libcrypto.so和libssl.so,于是自己下载8.0.26的仓库进行yum安装

1
2
3
4
5
yum install openssl-devel  # 先安装依赖
sudo yum install https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
# 我换了阿里云的centos8源
#base CentOS-8.5.2111 - Base - mirrors.aliyun.com就包含了mysql8.0.26仓库直接yum install就好了
yum install mysql-common mysql-server mysql-devel

启动mysql服务

1
2
systemctl start mysqld
systemctl status mysqld

登录mysql-server

默认生成密码在log日志中

1
2
3
4
grep "password" /var/log/mysql/mysqld.log #要么在log或者mysql里面
grep "password" mysqld.log
2024-11-09T07:41:40.103726Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
# 由于这里安装是没有添加--initialize-insecure,默认没有密码

登录后修改密码

1
2
3
4
set global validate_password.policy = 0;
set global validate_password.length = 1;
# 我安装的好像没有validate_password插件,直接修改就好了
ALTER USER 'root'@'localhost' IDENTIFIED BY 'root';

创建用户

默认的root用户只能当前节点localhost访问,是无法远程访问的,我们还需要创建一个账户,用户远程访问,

1
2
create user 'git'@'%' IDENTIFIED WITH mysql_native_password BY 'git';
grant all on *.* to 'git'@'%';

数据类型

image-20241123194409396

TIMESTAMP会自动更新时间,DATETIME需手动更新

常用函数

字符串函数

数值函数

时间和日期函数

NOW():返回当前的日期和时间

UNIX_TIMESTAMP(data):返回日期date的UNIX时间戳

CURRENT_TIMESTAMP、CURRENT_TIMESTAMP() :当前时间

CURDATE():当前日期

CURTIME():当前时间

DATE_FORMAT(date, “%y-%m-%d”):格式化日期时间等 聚合函数 count、sum、avg、max、min

聚合函数

count、sum、avg、max、min

MySQL完整性约束

primary key、auto_increment、unique、not null、default、foreign key

关系型数据库范式

目的:减少数据冗余

第一范式:每一列具有原子性

第二范式:属性完全依赖主键

第三范式:属性不依赖其他非主属性

BC范式:每个表中只有一个候选键

第四范式:消除表中的多值1依赖

范式越多,表越多,增加SQL查询复杂度,降低查询性能;第三范式已经很大程度上减少了数据冗余,并且 基本预防了数据插入异常,更新异常,和删除异常了。

核心SQL

DDL:

DML:增删改查记录

DCL:数据控制;访问权限和安全级别相关;grant、revoke

1
2
3
4
show databases;
create database ChatDB;
drop database ChatDB;
use ChatDB;
1
2
3
4
5
6
7
8
9
show table;
create table user(
id in unsigned primary key not null auto_increament,
name varchar(50) not null,
age tinyint not null,
sex enum('M','W') not null)engine=INNODB default charset=utf8;
desc user;
show create table user\G
drop table user;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
insert into user(nickname, name, age, sex) values('fixbug', 'zhang san', 22, 'M');
update user set age=23 where name='zhang san'
delete from user where age=23;
select id from user where sex='W' or age>=22;
select distinct name from user;
select * from user where name is null;

select country from websites union ALL select country from apps order by country; #union 默认去重

select * from user where id in(select stu_id from grade where average>=60.0);

select * from user limit 10;

select * from user where sex='M' and age>=20 order by age desc/asc;

select count(id),sex from user group by sex;

select a.uid,a.name,b.uid,b.name from table1 a inner join table2 b on a.uid=b.uid where a.uid=1;
select a.* from user a left outer join Orderlist b on a.uid=b.uid where a.orderid is null;
select a.* from user a right outer join Orderlist b on a.uid=b.uid where b.orderid is null;

Mysql存储引擎

种类 锁机制 B-树索引 哈希索引 外键 事务 索引缓存 数据缓存
MyISAM 表锁 支持 不支持 不支持 不支持 支持 不支持
InnoDB 行锁 支持 不支持 支持 支持 支持 支持
Memory 表锁 支持 支持 不支持 不支持 支持 支持

锁机制:表示数据库在并发请求访问的时候,多个事务在操作时,并发操作的粒度。

B-树索引和哈希索引:主要是加速SQL的查询速度。

外键:子表的字段依赖父表的主键,设置两张表的依赖关系。

事务:多个SQL语句,保证它们共同执行的原子操作,要么成功,要么失败,不能只成功一部分,失败需要回滚事务。

索引缓存和数据缓存:和MySQL Server的查询缓存相关,在没有对数据和索引做修改之前,重复查询可以不用进行磁盘I/O(数据库的性能提升,目的是为了减少磁盘I/O操作来提升数据库访问效率),读取上一次内存中查询的缓存就可以了。

Mysql索引

核心:提高查询速度

由于索引也是需要存储成索引文件的,因此对索引的使用也会涉及磁盘I/O操作。

1、普通索引:没有任何限制条件,可以给任何类型的字段创建普通索引(创建新表&已创建表,数量是不限的,一张表的一次sql查询只能用一个索引 where a=1 and b=’M’)

2、唯一性索引:使用UNIQUE修饰的字段,值不能够重复,主键索引就隶属于唯一性索引

3、主键索引:使用Primary Key修饰的字段会自动创建索引(MyISAM, InnoDB)

4、单列索引:在一个字段上创建索引

5、多列索引:在表的多个字段上创建索引 (uid+cid,多列索引必须使用到第一个列,才能用到多列索引,否则索引用不上)

6、全文索引:使用FULLTEXT参数可以设置全文索引,只支持CHAR,VARCHAR和TEXT类型的字段上,常用于数据量较大的字符串类型上,可以提高查询速度(线上项目支持专门的搜索功能,给后台服务器增加专门的搜索引擎支持快速高校的搜索 elasticsearch 简称es

C++开源的搜索引擎(搜狗的 workflow)

1
2
3
4
5
6
7
8
create table index1(
id INT,
name VARCHAR(20),
sex ENUM('male', 'female'),
INDEX(id, name));

CREATE [UNIQUE] INDEX 索引名 ON 表明 (属性名(length) [ASC|DESC]);
DROP INDEX 索引名 ON 表名;

explain查看索引执行过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> explain select Host,User from user where User='root'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: user
partitions: NULL
type: index
possible_keys: NULL
key: PRIMARY
key_len: 276
ref: NULL
rows: 4
filtered: 25.00
Extra: Using where; Using in

Using index表示直接从索引树上查询到结果,不需要回表

  • select_type

    simple:表示不需要union操作或者不包含子查询的简单select语句。有连接查询时,外层的查询 为simple且只有一个。

    primary:一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type即 为primary且只有一个。

    union:union连接的两个select查询,除了第一个表外,第二个以后的表的select_type都是 union。 union result:包含union的结果集,在union和union all语句中,因为它不需要参与查询,所以id 字段为null。

  • table

    显示查询的表名;

    如果不涉及对数据库操作,这里显示null;

    如果显示为尖括号就表示这是个临时表,后边的N就是执行计划中的id,表示结果来自于这个查询 产生的;

    如果是尖括号括起来也是一个临时表,表示这个结果来自于union查询的id为M,N 的结果集;

  • type

    const:使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type就是 const。

    ref:常见于辅助索引的等值查找,或者多列主键、唯一索引中,使用第一个列之外的列作为等值 查找会出现;返回数据不唯一的等值查找也会出现。

    range:索引范围扫描,常见于使用<、>、is null、between、in、like等运算符的查询中。

    index:索引全表扫描,把索引从头到尾扫一遍;常见于使用索引列就可以处理不需要读取数据文 件的查询,可以使用索引排序或者分组的查询。 all:全表扫描数据文件,然后在server层进行过滤返回符合要求的记录。

  • ref

    如果使用常数等值查询,这里显示const;

    如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段;

  • Extra

    using filesort:排序时无法用到索引,常见于order by和group by语句中。

    using index:查询时不需要回表查询,直接通过索引就可以获取查询的数据。

索引底层实现

MySQL支持两种索引,一种的B-树索引,一种是哈希索引,

基于B-树的索引结构:

m阶平衡树;叶子节点都在同一层;节点大小和block一致,磁盘IO次数最少

B-树

  1. 每个节点中有key,也有data,但是每一个节点的存储空间是有限的,如果data数据较大时会导致每个节点能存储的key的数据很小

  2. 当存储的数据量很大时同样会导致B-树的高度较大,磁盘IO次数花费增大,效率降低

image-20241123204723658

B+树

  1. B+树的非叶子节点只存关键字,不存数据地址。因此B+树的每一个非叶子节点存储的关键字是远远多于B-树的;从树的高度上来说,B+树的高度要小于B-树,使用的磁盘I/O次数少,因此查询会更快一些。
  2. B+树所有的数据都存在叶子节点上,因此在B+树上搜索关键字,找到对应数据 的时间是比较平均的,没有快慢之分。
  3. 做整表遍历和区间查找是非常容易的

image-20241123204839755

聚集和非聚集索引

MyISAM

使用B+树作为索引结构,叶子节点data域存放数据记录的地址

主索引要求key是唯 一的,而辅助索引的key可以重复

在磁盘上存储三个文件 user.frm(表结构文件) user.MYD(表的数据文件) user.MYI(表的 索引文件),这种方式叫非聚集索引

image-20241123210604346

InnoDB

image-20241123210901723

InnoDB存储引擎的主键索引,叶子节点中,索引关键字和数据是在一起存放的

InnoDB的辅助索引,叶子节点上存放的是索引关键字和对应的主键,因此先根据关键字找到对应主键,再到主键索引树找记录

在磁盘上只存储两种文件,user.frm(存储表的结构),user.ibd(存储索引和数据),这种叫做聚集索引

表必须有主键(没有显示指定会自动生成一个主键)

自适应哈希索引

自MySQL 5.7版本起,AHI的实现引入了分区机制,每个索引被分配到独立的分区,并由各自的锁存器进行保护,这一改进有效降低了高并发环境下的锁竞争问题。

通过哈希缓存结构跳过逐层定位

innodb_adaptive_hash_index_parts设置分区(减少锁竞争)

建立条件:

  1. 索引树要被使用足够多次

  2. hash info(1,0,true)

    • 检索条件与索引匹配列数
    • 第一个不匹配列中,两者匹配字节数
    • 匹配方向是否从左向右
  3. 索引树上的数据页要被经常使用

事务

1、事务是一组SQL语句的执行,要么全部成功,要么全部失败,不能出现部分成功,部分失败的结果。保证事务执行的原子操作。

2、事务的所有SQL语句全部执行成功,才能提交(commit)事务,把结果写回磁盘上。

3、事务执行过程中,有的SQL出现错误,那么事务必须要回滚(rollback)到最初的状态。

ACID特性

事务原子性、事务一致性、事务隔离性、事务持久性

事务隔离

脏读:一个事务读取另一个事务未提交的数据

不可重复读:一个事务操作导致另一个事务前后两次读到不同数据

幻读:一个事务前后查询结果不一致

隔离级别 脏读 不可重复读 幻读
读未提交
已提交读 ×
可重复读 × ×
串行化 × × ×
1
2
set autocommit=0;
set @@tx_isolation=REPEATABLE-READ;

锁机制

表级锁:对整张表加锁。开销小,加锁快,不会出现死锁;锁粒度大,发生锁冲突的概率高,并发度 低。

行级锁:对某行记录加锁。开销大,加锁慢,会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并 发度高。

排它锁(Exclusive),又称为X 锁,写锁。

共享锁(Shared),又称为S 锁,读锁。

X和S锁之间有以下的关系: SS可以兼容的,XS、SX、XX之间是互斥的

  • 一个事务对数据对象 O 加了 S 锁,可以对 O 进行读取操作但不能进行更新操作。加锁期间其它事 务能对O 加 S 锁但不能加 X 锁。
  • 一个事务对数据对象 O 加了 X 锁,就可以对 O 进行读取和更新。加锁期间其它事务不能对 O 加任 何锁。
  • 显示加锁:select … lock in share mode强制获取共享锁,select … for update获取排它锁

InnoDB

行级锁

InnoDB存储引擎支持事务处理,表支持行级锁定,并发能力更好。

1、InnoDB行锁是通过给索引上的索引项加锁来实现的,而不是给表的行记录加锁实现的,这就意味着 只有通过索引条件检索数据,InnoDB才使用行级锁,否则InnoDB将使用表锁。

2、由于InnoDB的行锁实现是针对索引字段添加的锁,不是针对行记录加的锁,因此虽然访问的是 InnoDB引擎下表的不同行,但是如果使用相同的索引字段作为过滤条件,依然会发生锁冲突,只能串 行进行,不能并发进行。

3、即使SQL中使用了索引,但是经过MySQL的优化器后,如果认为全表扫描比使用索引效率更高,此 时会放弃使用索引,因此也不会使用行锁,而是使用表锁,比如对一些很小的表,MySQL就不会去使用 索引。

间隙锁

select * from user where userid > 100 for update;

是一个范围条件的检索,InnoDB 不仅会对符合条件的 userid 值为 101 的记录加锁,也会对userid 大 于 101(但是这些记录并不存在)的”间隙”加锁,防止其它事务在表的末尾增加数据。

防止幻读,满足串行化隔离要求

意向共享锁和意向排他锁:事务计划加行级锁X/S前取得的锁

1、意向锁是由InnoDB存储引擎获取行锁之前自己获取的

2、意向锁之间都是兼容的,不会产生冲突

3、意向锁存在的意义是为了更高效的获取表锁(表格中的X和S指的是表锁,不是行锁!!!)

4、意向锁是表级锁,协调表锁和行锁的共存关系。主要目的是显示事务正在锁定某行或者试图锁定某 行。

表级锁

1)事务需要更新大部分或全部数据,表又比较大,如果使用默认的行锁,不仅这个事务执行效率低, 而且可能造成其他事务长时间等待和锁冲突;

2)事务涉及多个表,比较复杂,很可能引起死锁,造成大量事务回滚

死锁

MyISAM 表锁是 deadlock free 的, 这是因为 MyISAM 总是一次获得所需的全部锁,要么全部满足, 要么等待,因此不会出现死锁。但在 InnoDB 中,除单个 SQL 组成的事务外,锁是逐步获得的,即锁 的粒度比较小,这就决定了在 InnoDB 中发生死锁是可能的。

1.尽量使用较低的隔离级别

2.设计合理的索引并尽量使用索引访问数据,使加锁更加准确,减少锁冲突的机会提高并发能力

3.选择合理的事务大小,小事务发生锁冲突的概率小

4.不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序 存取表中的行。这样可以大大减少死锁的机会

5.尽量用相等条件访问数据,这样可以避免间隙锁对并发插入的影响

6.不要申请超过实际需要的锁级别

7.除非必须,查询时不要显示加锁

MVCC

是MySQL中基于乐观 锁理论实现隔离级别的方式,用于实现已提交读和可重复读隔离级别的实现

MVCC机制会生成一个数据请求时间点的一致性数据快照 (Snapshot), 并用这个快照来提供一定 级别 (语句级或事务级) 的一致性读取

MVCC多版本并发控制中,读操作可以分为两类:

1、快照读(snapshot read) 读的是记录的可见版本,不用加锁。如select

2、当前读(current read) 读取的是记录的最新版本,并且当前读返回的记录。如insert,delete,update,select…lock in share mode/for update

MVCC:每一行记录实际上有多个版本,每个版本的记录除了数据本身之外,增加了其它字段

DB_TRX_ID:记录当前事务

ID DB_ROLL_PTR:指向undo log日志上数据的指针

已提交读:每次执行语句的时候都重新生成一次快照(Read View),每次select查询时。

可重复读:同一个事务开始的时候生成一个当前事务全局性的快照(Read View),第一次select查询 时。

快照内容读取原则

1、版本未提交无法读取生成快照

2、版本已提交,但是在快照创建后提交的,无法读取

3、版本已提交,但是在快照创建前提交的,可以读取

4、当前事务内自己的更新,可以读到

MyISAM

MyISAM存储引擎不支持事务处理,因此它的并发比较简单,只支持到表锁的粒度,粒度比较大,并发 能力一般,但不会引起死锁的问题,它支持表级共享的读锁和互斥的写锁。

优化

  • concurrent_insert优化:

允许一个线程在读的时候,另外一个线程在尾部进行插入 (但是不能并发进行删除delete和更新update)

  • low_priority_updates优化:

MyISAM存储引擎不适合大量的更新操作和查询操作,因为查询操作获取读锁的优先级比较低,

mysql集群

1、数据备份 - 热备份&容灾&高可用

2、读写分离,支持更大的并发

主从复制

主从复制的流程:两个日志(binlog二进制日志&relay log日志)和三个线程(master的一个线程和 slave的二个线程)

1、主库的更新操作写入binlog二进制日志中。

2、master服务器创建一个binlog转储线程,将二进制日志内容发送到从服务器。

3、slave机器执行START SLAVE命令会在从服务器创建一个IO线程,接收master的binary log复制到其 中继日志。

​ 首先slave开始一个工作线程(I/O线程),I/O线程在master上打开一个普通的连接,然后开始 binlog dump process,binlog dump process从master的二进制日志中读取事件,如果已经跟上 master,它会睡眠并等待master产生新的事件,I/O线程将这些事件写入中继日志。

4、sql slave thread(sql从线程)处理该过程的最后一步,sql线程从中继日志中读取事件,并重放其 中的事件而更新slave机器的数据,使其与master的数据一致。只要该线程与I/O线程保持一致,中继日 志通常会位于os缓存中,所以中继日志的开销很小。

image-20241123222917067

读写分离

读写分离就是在主服务器上修改,数据会同步到从服务器,从服务器只能提供读取数据,不能写入,实 现备份的同时也实现了数据库性能的优化,以及提升了服务器安全。

分库分表

垂直分表:基于列字段进行大表拆表

垂直分库:对不用业务进行拆分,放在多个服务器上

水平分表:

水平分库分表:将单张表数据切分到多个服务器,每个服务器有相应的库与表,只是表中数据集合不同

image-20241123223558950

面试问题

一、范式设计

Q: 什么是数据库范式?
A: 范式是数据库设计中为了减少数据冗余、保证数据一致性而遵循的一系列规则。第一范式要求每个列不可再分;第二范式在第一范式基础上,非主属性完全依赖于主键;第三范式在第二范式基础上,非主属性不传递依赖于主键。

Q: 假设有员工表(员工编号,姓名,部门编号,部门名称),它满足第几范式?如果不满足如何拆分?
A: 该表不满足第三范式,因为部门名称传递依赖于员工编号。可以将部门信息拆分到单独的部门表(部门编号,部门名称),员工表只保留员工编号,姓名和部门编号。

二、SQL

Q: 写出从 “orders” 表(包含订单号、客户编号、订单金额)和 “customers” 表(包含客户编号、客户姓名)中查询出每个客户的订单总金额并按金额降序排列的 SQL 语句。
A:

1
2
3
4
5
SELECT c.customer_name, SUM(o.order_amount) AS total_amount
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_name
ORDER BY total_amount DESC;

Q: 如何在 SQL 中实现分页查询,获取第 5 - 10 条记录?
A: 在 MySQL 中可以使用 LIMIT 关键字,例如:

1
SELECT * FROM some_table LIMIT 4, 6; 

这里 4 表示偏移量(从第 5 条开始,索引从 0 开始),6 表示获取的记录数。

三、索引

Q: 索引的作用是什么?
A: 索引就像书籍的目录,能快速定位数据,加快数据的查询速度。它通过特定的数据结构(如 B - Tree)存储了表中一列或多列的值以及对应的行指针,减少数据库查询时的全表扫描。

Q: 有一个产品表(产品 ID,产品名称,产品类别,价格,库存),哪些字段适合创建索引?
A: 产品 ID 通常适合创建索引,因为常作为查询条件用于精确查找某个产品。产品类别如果经常用于查询过滤也可创建索引。价格字段如果在查询范围(如查找某价格区间的产品)或排序操作中频繁使用,也可考虑创建索引。而库存字段,如果更新频繁且很少用于查询条件,则不太适合创建索引。

四、存储引擎

Q: InnoDB 和 MyISAM 存储引擎的主要区别有哪些?
A: InnoDB 支持事务,具有 ACID 特性,采用行级锁,支持外键约束;MyISAM 不支持事务,查询速度相对较快(适用于读多写少场景),采用表级锁,不支持外键约束。

Q: 在社交网络系统中,发布动态和查看动态频繁,应选择哪种存储引擎?
A: 对于发布动态涉及写操作且需要事务保证数据一致性(如发布成功或失败的完整性),查看动态是读操作,综合考虑应选择 InnoDB 存储引擎。

五、事务

Q: 解释事务的 ACID 特性。
A: 原子性指事务是不可分割的操作单元,要么全部成功,要么全部失败回滚;一致性指事务执行前后数据库状态保持一致;隔离性指多个事务并发执行时相互隔离,互不干扰;持久性指事务一旦提交,对数据库的修改就是永久性的,即使系统故障也不会丢失。

Q: 事务隔离级别有哪些?
A: 有读未提交、读已提交、可重复读和串行化。读未提交可能出现脏读问题;读已提交解决脏读但有不可重复读问题;可重复读解决不可重复读但可能有幻读问题;串行化级别最高,解决所有并发问题但性能较差,事务串行执行。

六、锁 + MVCC

Q: 解释 MySQL 中的共享锁和排他锁。
A: 共享锁(S 锁)允许多个事务同时对同一数据加锁进行读取操作;排他锁(X 锁)则在一个事务对数据加锁后,其他事务不能对该数据进行读和写操作。

Q: 什么是 MVCC?它如何解决并发问题?
A: MVCC 即多版本并发控制。它为每行数据保存多个版本,每个版本有创建和删除时间。事务读取数据时根据事务开始时间和隔离级别选择合适版本。在读写并发场景中,读操作不会阻塞写操作,写操作也不会阻塞读操作(在一定隔离级别内),减少了锁冲突,提高了并发性能。

七、日志

Q: 介绍 MySQL 二进制日志(binlog)和事务日志(redo log 和 undo log)的作用。
A: 二进制日志记录了数据库的所有更改操作(除 SELECT),用于数据备份、主从复制等。redo log 用于在系统崩溃后恢复已提交事务修改的数据,保证数据持久性;undo log 用于回滚未完成的事务,保存事务修改前的数据状态。

Q: 如何利用二进制日志恢复数据?
A: 首先要确定恢复的时间点或位置,然后使用 MySQL 的 binlog 恢复工具(如 mysqlbinlog)结合数据库备份,按照 binlog 记录的操作顺序,将数据恢复到指定状态。

八、主从复制 + 读写分离

Q: 详细描述 MySQL 主从复制原理。
A: 主数据库将更改操作记录在二进制日志(binlog)中,从数据库的 I/O 线程读取主数据库的 binlog,并写入自己的中继日志(relay - log),然后从数据库的 SQL 线程从中继日志读取操作并执行,从而实现数据同步。

Q: 读写分离中如何确保数据一致性?
A: 可以采用半同步复制等方式,主库在写入数据后等待至少一个从库确认收到 binlog 并写入 relay log 后才返回客户端写操作成功。同时,在应用层可以设置数据校验机制,定期检查主从数据是否一致,若不一致则进行数据修复操作。

九、数据库中间件

Q: 数据库中间件的作用是什么?
A: 它在应用程序和数据库之间协调管理,功能包括数据分片(将数据按规则分布到多个数据库节点)、读写分离(路由读写请求到不同数据库实例)、连接池管理(提高连接复用率)、负载均衡(均匀分配请求到多个数据库实例)等,提升数据库整体性能和可扩展性。

Q: MyCAT 和 Sharding - Sphere 有何区别?
A: MyCAT 是开源分布式数据库中间件,配置相对复杂,对 SQL 有改写和解析能力,支持多种分片和读写分离策略。Sharding - Sphere 功能强大,支持多种分片策略和多种数据库,提供 Java API 和 SQL 解析,在分布式事务处理上有灵活方案,对应用代码侵入性较小。

十、分库分表

Q: 分库分表的主要策略有哪些?
A: 水平分表是将一个表按某规则(如时间、用户 ID 等)拆分成多个表;垂直分表是将表的列按业务逻辑拆分;水平分库是将数据库中的表按规则(如业务模块、地域等)拆分到多个数据库;垂直分库是将不同业务模块的表拆分到不同数据库。

Q: 分库分表后如何处理跨库跨表查询?
A: 可以通过数据库中间件进行 SQL 解析和改写,将跨库跨表查询拆分成多个单库单表查询,然后在中间件层合并结果集。也可以在应用层进行逻辑处理,分别查询多个库表后自行合并数据,但这种方式对应用代码复杂度有一定影响。