Mysql高级
2021-07-07 21:43:08 8 举报
AI智能生成
mysql高级优化总结(偏向java优化)
作者其他创作
大纲/内容
MYSQL高级
mysql架构介绍
mysql简介
高手的 mysql 是怎样炼成的?
数据库内部结构和原理
数据库建模优化
数据库索引的建立
sql语句优化
mysql 服务器的安装配置
数据库的性能监控分析与系统优化
mysql服务器的优化
各种参数常量设定
查询语句优化
主从复制
软硬件升级
容灾备份与恢复
shell 或 python 等脚本语言开发
对开源数据库进行二次开发
mysql linux的安装(5.7)
检查当前系统是否安装过mysql
安装mysql服务端
安装mysql客户端
查看mysql安装时创建的mysql用户和mysql组
mysql服务的启动和停止
mysql服务状态
启动 mysql
systemctl start mysqld
重启 mysql
systemctl restart mysqld
停止 mysql
systemctl stop mysqld
查看mysql 状态
systemctl status mysqld
修改配置文件的位置
问题
linux 向表中插入一条中文字符报错误
修改全局配置文件(vim etc/my.cnf)
character-set-server=utf8
表修改类型字符集
alter table xs modify name varchar(30) character set utf8;
修改已有数据库的字符集
alter database 库名 character set 'utf8';
mysql的用户与权限管理(远程访问mysql)
mysql 用户管理
创建用户
create User zs identified by '123123'
授权
grant all privileges on *.* to root @'%' identified by '123123'
修改用户密码
set password = password('123456')
如果navite 远程连接失败 注意:防火墙要开放3306端口
查看防火墙状态
systemctl status firewalld
开启防火墙
service firewalld start
关闭防火墙
service firewalld stop
重启防火墙
service firewalld restart
如果开启防火墙则需要开放端口
开放3306
firewall-cmd --zone=public --add-port=3306/tcp --permanent
firewall-cmd --reload
查看防火墙开放端口
firewall-cmd --list-ports
mysql 的一些杂项配置
sql_mode
创建表
结论: group by 使用原则 select 后面只能放函数 和 group by 后的字段
如何查看sql_mode
show variables like '%sql_mode%';
把公司服务器的sql_mode验证修改为本地的服务器的sql_mode
mysql 配置文件
二进制日志 log-bin
错误日志 log-err
查询日志 log
数据文件
俩系统
windows
mysql安装路径/data
linux
使用命令查看全部库
frm文件
存放表结构
myd文件
存放表数据
myi文件
存放表索引
如何配置
windows配置文件
my.ini
linux配置文件
/etc/my.conf
mysql 逻辑架构介绍
总体概览
执行步骤为以下几步
利用 show profile 查看sql的执行计划
修改配置文件 /etc/my.cnf
query_cache_type=1
开启 profiling
查看 profiling 是否开启
show variables like '%profiling%';
开启这样设置 set profiling =1 ;
select * from 表名
show profiles; 查看执行计划
mysql 存储引擎
查看命令
innodb 和 myisam
行表锁谁会发生死锁?
行锁
什么情况下会用到 MyISAM存储引擎?
各个存储引擎介绍
InnoDB
MyISAM
Archive
Blackhole
CSV
memory
federated
索引优化分析
查询语句写的烂
单值索引
复合索引
关联查询有太多的join(设计缺陷或不得已的需求)
sql优化
调整 my.cnf
没有充分利用到索引
建立索引
数据过多
分库分表
常见通用的join查询
sql的执行顺序
手写
机读
总结
7中join图
建表sql语句
查询语句
font color=\"#0076b3\
索引简介
索引是什么?
排好序的快速查找数据结构就是索引
详解(二叉树)
Mysql索引为什么没有使用二叉树???
结论
font color=\"#c41230\
优势
span style=\"font-size: inherit;\
通过索引对数据列进行font color=\"#c41230\
劣势
Mysql 索引结构(平衡树)
什么是平衡树
BTree索引
原理图
B+Tree索引
B树和B+树的区别
B树的关键字和记录是放在一起的,叶子节点可以看作外部节点,不包含任何信息;B+树的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。
在B树中,越靠近根节点的记录查找时间越快,只要找到关键字即可确定记录的存在;而B+树中每个记录的查找时间基本是一样的,都需要从根节点走到叶子节点,而且在叶子节点中还要再比较关键字。
那么为什么说B+树比B-树更适合实际应用中操作系统的文件索引和数据库索引?
B+树的磁盘读写代价更低
B+树的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。
B+树的查询效率更加稳定
由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
时间复杂度(时间一去不复返)
聚簇索引与非聚簇索引
聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。术语‘聚簇’表示数据行和相邻的键值聚簇的存储在一起。如下图,左侧的索引就是聚簇索引,因为数据行在磁盘的排列和索引排序保持一致
空间复杂度(可以用钱买)
空间复杂度全称就是渐进空间复杂度(asymptotic space complexity),表示算法的存储空间与数据规模之间的增长关系。
mysql索引分类
create index 索引名 on 表名(索引字段);
唯一索引
create unique index 索引名 on 表名(表字段)
主键索引
即一个索引包含多个列
基本语法
索引
alter四种方式建立索引
不给你索引名根据font color=\"#c41230\
查询索引名(information_schema库的STATISTICS 表)
怎么把字符串转变为sql
使用游标 和 预编译
使用存储过程进行删除
mysql索引结构
检索原理
hash索引
full-text全文索引
r-tree索引
那些情况下可以建立索引
主键自动建立唯一索引
频繁作为查询字段应该建立索引
频繁更新的字段不适合建立索引
where 条件用不到字段不需要创建索引
单键/组合索引选择问题 who? 在高并发的情况下使用组合索引
查询中统计或者分组字段
那些情况下不要建立索引
表记录太少
经常增删改的字段
where 条件里用不到的字段不创建索引
过滤性不好的不适合建立索引
性能分析
Mysql Query Optimizer
mysql常见性能瓶颈
CPU: CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据的时候
IO: 磁盘I/O 瓶颈发生在装入数据远大于内存容量的时候
Explain
是什么(执行计划)
能干嘛
表的读取顺序(id)
数据读取操作的操作类型(selecttype)
那些索引可以使用(possiblekeys)
那些索引被实际使用(key)
表之间的引用(ref)
每张表有多少行被物理查询(rows)
怎么玩
Explain + sql语句
执行计划包含的信息
字段解释
id
又分为三种顺序
select_type
有哪些类型
table
partitions
type
显示查询使用了何种类型 从最佳到最差依次是: system > const > eq_ref > ref > range > index > ALL
system
const
eq_ref
ref
range
all
full table scan 将遍历全表以找到匹配的行
index_merge
ref_or_null
index_subquery
unique_subquery
该连接类型类似于 index_subquery 子查询中的唯一索引
备注 : font color=\"#c41230\
如果你的type类型为 all 并且你的数据在 百万以上的请你优化你的sql语句
possiblekeys
显示font color=\"#c41230\
key
key_len
rows
rows 列显示Mysql 认为它执行查询时必须检查的行数 (值越小越好)
filtered
filtered列表示将按表条件筛选的表行的估计百分比。最大值为100,这意味着没有对行进行筛选。值从100减小表示过滤量增加。rows显示检查的估计行数,rows×filtered显示将与下表联接的行数。例如,如果rows为1000,filtered为50.00(50%),则要与下表联接的行数为1000×50%=500。
Extra
包含不适合在其它列中显示但十分重要的额外信息
Using filesort(要你命三千)
如何出现问题?
如何解决这个问题呢?
Using temporary(要你命三万)
如何出现这个问题?
如何解决这个问题呢?( group by 包含一个排序 和 分组)
Using index
如果同时出现?
只有一个?
覆盖索引(Covering Index)
Using where
表名使用了 where 过滤
Using join buffer
使用了连接缓存
Impossible WHERE
WHERE子句总是false,不能用来获取任何元组
Select tables optimized away
Distinct
热身case
索引优化
索引分析
单表优化
创表语句
问题及优化
问题?
解决思路1
解决思路2
俩表优化
建表语句
left join案例分析1
left join案例分析2
三表优化
Join优化总结
索引失效(应该避免)
建表sql
单表-索引失效的原因
如果只用到覆合索引的其中一个或者多个又会如何呢?
只查覆合索引第一个
只查覆合索引前俩个
全值匹配
创建的索引是 nameAgePos 这时我们只查Age 和 pos
创建的索引是 nameAgePos 这时我们只查 pos
口诀1 : font color=\"#c41230\
我们创建的索引 nameAgePos 这时我们只查 name与Pos
过程和结果同样重要
问题查询name为 july的用户信息
方式1
方式2
但是它们的执行过程一个天上一个地下
范围之后全失效
使用 *
不使用 *(返回索引字段)
不使用* 且查询包含 < 或者>
等于 =
不等于 !=
不等于 <>
is null
is not null
like查询%号写右边
方式3
问题?(解决like %xx% 时索引不被引用的方法?)
覆盖索引(你建的索引和你查的字段个数顺序上最好完全一致)
覆合索引 nameAgePos
生效
查询语句1
查询语句2
查询语句3
查询语句4
失效
语句1查询 索引之外字段
语句2 select*查询全部字段
语句1(加单引号)
语句2(不加单引号)
使用or 关键字索引失效
单表-一般性建议
单表-口诀
关联表查询优化
left /right join案例
explain select * from class left join book on class.card=book.card;
结论: 这是 book表使用了索引 type类型为 ref 笛卡尔结果集为 20 其中Extra 也没有了 Using join buffer
如果我们在给class 表的card 也建立索引是否能更快的查询到数据呢? create index idx_class_card on class(card); 再次执行 explain 语句
inner join 案例
结论: 如果用的是inner join mysql自己选择 驱动表和被驱动表
关联查询-建议
保证被驱动表的join字段已经被索引
子查询优化
尽量不要使用 not in 或者 not exists 用left join 表名 on xxx is null 来代替它
面试题讲解
案例(我们创建的覆合索引 idx_test03_c1234 根据以下sql分析下索引的使用情况)
热身(都按照索引顺序来进行查询)
全值匹配我最爱
前俩个索引
只查最左侧索引
查左侧的三个索引
索引顺序和where查询的顺序不同(不包含< 或者 >)
explain select * from test03 where c1='a1' and c2='a2' and c4='a4' and c3='a3';
explain select * from test03 where c4='a4' and c3='a3' and c2='a2' and c1='a1';
索引顺序和where查询的顺序不同(包含< 或者 >)
explain select * from test03 where c1='a1' and c2='a2' and c3 >'a3' and c4='a4';
explain select * from test03 where c1='a1' and c2='a2' and c4 >'a4' and c3='c3';
索引中使用 order by(出现 Using filesort 就是没有用到索引)
explain select * from test03 where c1='a1' and c2='a2' and c5='a5' font color=\"#c41230\
explain select * from test03 where c1='a1' font color=\"#c41230\
explain select * from test03 where c1='a1' and c5='a5' font color=\"#c41230\
explain select * from test03 where c1='a1' and c2='a2' order by c4;
explain select * from test03 where c1='a1' and c2='a2'order by c3;
explain select * from test03 where c1='a1' and c2='a2'and c4='a4' order by c3;
再次执行explain 语句
创建覆合索引 create index idx_emp_ageDeptidName on emp(font color=\"#c41230\
explain select SQL_NO_CACHE * from emp where age=1 order by deptId font color=\"#c41230\
排序分组优化
索引的选择
create index idx_emp_ageEmpno on emp(font color=\"#c41230\
explain 执行sql语句( type 类型为 range rows 为 4000多行 会出现手动排序的Using filesort)
create index idx_emp_ageName on emp(font color=\"#c41230\
explain 执行sql语句 (type 类型为 ref rows 物理扫描行数为 5w行)
总结: 如果上面俩个索引(idx_emp_ageEmpno 和 idx_emp_ageName ) 这时mysql 会选择 font color=\"#c41230\
索引中使用 group by
explain select * from test03 where c1='a1' and c4 ='a4' font color=\"#c41230\
总结: font color=\"#c41230\
like 模糊查询
explain select * from test03 where c1='a1' and c2 like 'a2%'and c3='a3';
explain select * from test03 where c1='a1' and c2 like '%a2'and c3='a3';
explain select * from test03 where c1='a1' and c2 like '%a2%'and c3='a3';
explain select * from test03 where c1='a1' and c2 like 'a%a2%'and c3='a3';
一般性建议
尽可能通过分析统计信息和调整Query 的写法来达到选择合适索引的目的
索引优化口诀
查询截取分析
查询优化
永远小表驱动大表 (类似嵌套循环 Nested Loop)
注意: emp表和dept表应该建立索引
in
EXISTS
order by关键字优化
order by能不能产生filesort
不能产生filesort的sql
explain select * from tblA where age>20 order by age;
explain select * from tblA where age>20 font color=\"#c41230\
explain select * from tblA where birth > '2020-09-23 14:26:15' order by age;
能产生filesort
explain select * from tblA where age>20 order by birth;
explain select * from tblA where age>20 font color=\"#c41230\
explain select * from tblA where birth > '2020-09-23 14:26:15' order by birth;
explain select * from tblA font color=\"#c41230\
order by语句使用最左前缀法则
使用Where 子句与 Order by 子句条件列组合满足索引最最左前缀
结论 : font color=\"#c41230\
单路排序
双路排序
结论及引申出来的问题?
优化策略
增大 sort_buffer_size的容量
增大 max_length_for_sort_data参数的设置
why?(提高order by 的速度)
总结和查询要点(为排序使用索引)
Case (创建索引 key_a_b_c)
order by使用最左前缀
order by a
where a=const and b=const order by c
不能使用索引进行排序
where a=const order by c (中间兄弟 b 不能丢)
Group by关键字优化
最后使用索引的手段: 覆盖索引(简单来说就是 select 和到 from 之间查询的列 <= 使用的索引列 + 主键)
explain select * from emp where age <> 30;
结论: type 类型为 全表扫描 rows 为50w行
explain select font color=\"#c41230\
结论: type类型为 range 使用到了索引 rows为25w行
总结: 写sql不要写 * 写具体的字段
慢查询日志
是什么?
怎么玩?
说明
查看是否开启及如何开启
默认
show variables like '%slow_query_log%';
全局开启
set global slow_query_log=1;
永久开启慢查询日志如何做呢?
查看默认阈值
show variables like '%query_time%';
修改为阈值大于3的慢sql
set long_query_time=3;
Case分析
默认睡4秒的sql : select sleep(4);
然后去你的 slow_query_file 路径下面查看你的慢sql
如何查看当前系统存在多少条慢sql
show global status like '%Slow_queries%';
配置版本怎么玩呢?
日志分析工具 mysqldumpslow
s : 是表示按照何种方式排序
c : 访问次数
l : 锁定时间
r : 返回记录
t : 查询时间
al :平均锁定时间
ar : 平均返回记录数
at : 平均查询时间
t : 即返回前面多少条的数据
mysqldumpslow 工作常用参考
得到返回记录集最多的10个sql集合
mysqldumpslow -s r -t 10 /var/lib/mysql/host_name-slow.log
得到返回次数最多的10个sql
mysqldumpslow -s c -t 10 /var/lib/mysql/host_name-slow.log
按照时间排序的前10条里面包含有左连接的查询语句
mysqldumpslow -s t -t 10 -g \"left join\" /var/lib/mysql/host_name-slow.log
批量数据脚本
设置参数 log_bin_trust_function_creators
show variables like '%log_bin_trust_function_creators%';
开启
set global log_bin_trust_function_creators=1;
随机产生字符串
随机产生部门编号
创建存储过程
创建emp表中插入数据的存储过程
创建dept表中插入数据的存储过程
插入数据
dept表插入
emp表插入
show Profile
是什么?
默认情况是关闭的
show variables like '%profiling%';
保存最近15次的运行结果
开启 profile
set profiling=1;
分析
运行sql
select * from emp group by id%20 order by 5;
select * from emp group by id%10 limit 150000;
查看结果
show profiles
all : 显示所有的开销信息
block io : 显示块IO相关开销
context switches : 上下文切换相关开销
cpu : 显示cpu相关开销信息
ipc : 显示发送和接受相关开销的信息
memory : 显示内存相关开销信息
page faults : 显示页面错误相关开销信息
swaps : 显示交换次数相关开销信息
日常开发中需要出现的问题
status状态栏出现下面几种情况
Creating tmp table 创建临时表
拷贝数据到临时表
用完再删除
locked
show processlist(展现进程列表)
可以使用 kill id
全局查询日志
永远不要在生产环境开启这个功能
配置启用
编码启用
查看 select * from mysql.general_log;
工具和技巧拾遗
视图 View
什么是视图?
将一段查询的sql封装为一个虚拟的表
作用
适用场景
很多地方可以共用的一组查询结果
报表
创建/更新语法
创建
create view 视图名 as sql语句
使用
select * from view_test
更新
create font color=\"#c41230\
注意事项(使用 5.5)
mysql 锁机制
概念
什么是锁?
生活购物
锁的分类
从对数据库操作的类型进行分类
读锁
写锁
从对数据库操作的粒度分类
表锁(偏读)
手动增加表锁
查看锁的命令
show open tables;
加锁
lock table mylock font color=\"#c41230\
解锁
unlock tables;
读锁/写锁对我们性能有什么影响?
表锁分析
通过命令 show open tables 查看那个表被锁了
如何分析表锁定呢?
show status like '%table%';
行锁(偏写)
事务及ACID属性
原子性
一致性
事务必须使数据库从一个一致性状态切换到另一个一致性状态。
隔离性
持久性
并发事务处理带有的问题
更新丢失(Lost Update)
脏读 (Dirty Reads)
不可重复读(Non-Repeatable Reads)
幻读( Phantom Reads)
mysql数据库的隔离级别(常用到不经常用)
repeatable read (读未提交的数据)
read committed (读已提交的数据)
read uncommitted (可重复读)
serializable (串行化)
查看mysql隔离级别
show variables like '%tx_isolation%';
行表锁的基本演示
关闭数据库的自动提交
默认是开启的查询命令是: show variables like '%autocommit%';
关闭命令是 : set autocommit = 0;
更新同一行
更新不是同一行
无索引行锁升级为表锁
由于varchar使用单引号引起的行锁变为表锁
a客户端
b客户端就会阻塞
间隙锁危害
如何产生
data
a客户端使用范围进行updat批量修改数据
b客户端插入一个范围之内没有的值(发生阻塞)
面试题: 如何锁定某一行
锁定一行
行锁分析
检查行锁争夺情况
show status like '%innodb_row_lock%'
字段说明
Innodb_row_lock_waits
系统启动后到现在锁定总共等待的次数
Innodb_row_lock_time_max
从系统启动到现在等待最长的一次花费的时间
Innodb_row_lock_time_avg
每次等待平均花的平均时间
Innodb_row_lock_time
从系统启动到现在锁定总时间长度
Innodb_row_lock_current_waits
当前系统正在等待锁定的数量
优化建议
尽可能低级别事务隔离
页锁
主从复制的基本原理
slave 会从mast读取binlog来进行数据同步
mysql复制过程分成三步
复制的基本原则
每个salve只有一个 master
每个salve只能有一个唯一的服务器ID
每个master 可以有多个salve
复制的最大问题
网络延时
一主一从的常见配置
前提条件
mysql 版本一致且后台以服务运行
双向网络是否ping通
主从复制都配置在 [mysqld]节点下面.都是小写
修改主机配置文件 (my.ini)文件
server-id=1
log-bin=mysql-bin
log-err=本地mysql路径/mysqlerr
basedir=mysql本地路径
tmpdir=mysql本地路径
datadir=mysql本地路径/data
read-obly=0
binlog-ignore-db=mysql
binlog-do-db=数据库名
binlog_format=STATEMEN(默认)
修改从机my.cnf文件
server-id=2
linux 查看防火墙状态
主机和从机设置
主机
grant replication slave on *.* to '账号'@'从机数据库ip' identified by '密码' ;
刷新权限
flush privileges;
查看主机的状态
show master status;
从机
change master to master_host='font color=\"#c41230\
启动slave
start slave
查看从机状态
show slave status \\G;
如下执行成功
从机出现 问题 ERROR 3021 (HY000): This operation cannot be performed with a running slave io thread; run STOP SLAVE IO_THREAD FOR CHANNEL '' first.
stop slave;
reset master;
测试内容
主机新建表新建库增加数据
从机测试数据
Mycat 8066端口
介绍
数据库中间件
干什么的
读写分离
数据分片
垂直拆分
水平拆分
垂直+水平拆分
多数据源整合
原理
拦截
Mycat 的原理中最重要的一个动词就是 font color=\"#c41230\
安装
下载地址 https://github.com/MyCATApache/Mycat-download
把 mycat 文件的所有内容 copy 到/user/local/
cp -r mycat/ /usr/local/
修改配置文件
server.xml
user name=\"mycat\" name=\"password\" 123456 name=\"schemas\">TESTDB
schema.xml
删除 <schema></schema> 里面的所有内容
显示行数
:set nu
添加 <schema dataNode=\"dn1\"></schema>
修改 <dataNode dataHost=\"host1\" database=\"自己数据库名\"></dataNode>
修改 <dataHost name=\"host1\"></dataHost>
<writeHost url=\"192.168.73.1:3306\" user=\"root\" password=\"root\"></writeHost>
<readHost host=\"hostS2\" url=\"192.168.1.200:3306\" user=\"root\" password=\"root\" />
修改完如下
rule.xml
验证数据库访问情况
(2个主机的mysql都需进行检验)mysql -uroot -proot -h 192.168.73.131 -P 3306
如果出现错误(ERROR 1045 (28000): Access denied for user 'root'@'192.168.73.131' (using password: YES))
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
flush privileges;
启动程序
控制台启动
在 mycat/bin目录下
mycat console
后台启动
在 mycat/bin目录下
mycat start
启动时可能出现报错
域名解析失败
修改 etc/hosts文件添加linux用户名
如何查看linux用户名
hostname
添加系统名etc/hosts文件中
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 localhost.localdomain
Unable to start JVM: No such file or directory (2)
修改 mycat中conf里面的wrapper.conf
wrapper.java.command=java安装目录/bin/java
Unable to start JVM: Permission denied (13)
登录
后台管理窗口
mysql -urooot -proot -P9066 -h ip地址
数据窗口(默认启动)
mysql -urooot -proot -P8066 -h ip地址
读写分离(先实现主从复制然后才能实现读写分离)
schema.xml(balance=?)
0(默认)
1
2
所有读操作都font color=\"#c41230\
3
@@hostname 使俩个库插入不同的用户名来查看
分库
配置完成如下
分表操作(订单表 -orders)
订单表 根据customer_id 进行分表
增加一行
<table name=\"orders\" dataNode=\
<tableRule name=\"mod_rule\"> <rule> <columns>customer_id</columns> <algorithm>mod-long</algorithm> </rule> </tableRule>
<function name=\"mod-long\" class=\"io.mycat.route.function.PartitionByMod\"> <!-- how many data nodes --> <property name=\"count\">2</property> </function>
问题? font color=\"#c41230\
跨库join
ER表(订单详情表-orders_detail)
添加orders的字表 orders_detail的 schema.xml
name=\"orders_detail\" :字表订单详情表表名
primaryKey=\"id\" id 是订单标详情的主键id
joinKey=\"order_id\" order_id 是订单详情表的字段关联父类的字表字段
parentKey=\"id\" id 是orders 表关联字表的字段
插入
关联查询sql
全局表(dict_order_type)
<table name=\"dict_order_type\" dataNode=\
向订单字典表插入数据
全局序列
1数据库方式
数据库序列方式原理
建序列表
建存储过程和函数
mysql 建存储过程出现的问题
show variables like '%log_bin_trust_function_creators%';
执行它解决问题 set global log_bin_trust_function_creators=TRUE;
修改mycat配置文件
sequence_db_conf.properties
ORDERS=dn1
<property name=\"sequnceHandlerType\">1</property>
插入语句
自主生成
根据业务逻辑组合
利用redis单线程原子性 incr来生成序列
0 条评论
回复 删除
下一页