mysql 存储引擎_MySQL 存储引擎

一、MySQL存储引擎种类

查看命令:show engines;

MRG_MYISAM

CSV

MyISAM

BLACKHOLE

PERFORMANCE_SCHEMA

InnoDB

ARCHIVE

MEMORY

FEDERATED

其他产品存储引擎(percona、mariadb)

TokuDB

MyRocks

二、InnoDB 核心特性介绍

1、聚簇索引(Clustered index )

用来组织存储数据和优化查询

2、修改缓冲区(Change buffer)

3、自适应hash索引:AHI

4、MVCC

多版本并发控制

5、多缓冲区池

减少磁盘IO

6、事务

数据安全保证

7、行级锁粒度

控制并发

8、外键

9、支持更多复制特性

10、支持热备

11、自动故障恢复(CSR)

12、双写机制(Double Write)

三、存储引擎管理

(一)、默认存储引擎修改

1、会话级别

set default_storage_engine=myisam;

2、全局级别(仅影响新会话)

set global default_storage_engine=myisam;

3、永久生效

vim /etc/my.cnf

[mysqld]
default_storage_engine=myisam

systemctl restart mysql

(二)、查看所有生产表的存储引擎

select table_schema,table_name ,engine 
from information_schema.tables 
where table_schema not in ('sys','mysql','information_schema','performance_schema');

(三)、修改表的存储引擎

alter table 表名称 engine=引擎名称;

例:alter table x engine=innodb;

(四)、批量修改存储引擎

将zabbix库中的所有表,innodb替换为tokudb

select concat("alter table zabbix.",table_name," engine tokudb;") 
from information_schema.tables 
where table_schema='zabbix' 
into outfile '/tmp/tokudb.sql';

source /tmp/tokudb.sql

将所有非InnoDB业务表查询出来,并修改为InnoDB

select concat("alter table ",table_schema,".",table_name," engine=innodb;" )
from information_schema.tables 
where engine != 'InnoDB'
and table_schema not in ('sys','performance_schema','information_schema','mysql')
into outfile '/tmp/alter.sql' ;

source /tmp/alter.sql

四、MySQL 存储引擎体系结构

(一)、宏观结构

1、MyISAM

myt.frm : 数据字典信息(列的定义和属性)

myt.MYD : 数据行

myt.MYI : 索引

2、InnoDB

city.frm : 数据字典信息(列的定义和属性)

city.ibd(独立表空间文件) : 数据行和索引

ibdata1 (共享表空间文件) : 数据字典信息,UNDO(事务回滚日志),double write 磁盘区域,change buffer磁盘区域

(二)、InnoDB 微观结构(体系结构)

1、磁盘

①、数据存储

a,表空间

表空间概念

表空间概念是引入于Oracle数据库。

起初为了解决存储空间扩展的问题。MySQL5.5 版本引入了共享表空间模式。

表空间结构

表 ----> 表空间 ---> 段 ---> 多个区 ---> 连续的page ---> 连续的block ----> 连续的扇区

MySQL 表空间类型

1、共享表空间

用来存储:系统数据,日志,undo,临时表,用户数据和索引

2、独立表空间

5.6 版本默认独立表空间模式。单表单表空间。

3、普通表空间

完全和Oracle一致的表空间管理模式

4、undo表空间

存储undo logs(回滚日志)

5、临时表空间

6、存储临时表。5.7 默认独立

b.共享表空间

共享表空间演变

5.5版本:

系统相关:(全局)数据字典信息、UNDO回滚信息、Double Write信息、临时表信息、change buffer

用户数据: 表数据行、表的索引数据

5.6版本:共享表空间只存储于系统数据,把用户数据独立了。

系统相关:(全局)数据字典信息、UNDO回滚信息、Double Write信息、临时表信息、change buffer

5.7版本:在5.6基础上,把临时表独立出来,UNDO也可以设定为独立

系统相关:(全局)数据字典信息、UNDO回滚信息、Double Write信息、change buffer

8.0.19版本:在5.7的基础上将UNDO回滚信息默认独立

系统相关:Double Write信息、change buffer

8.0.20版本:在之前版本基础上,独立 Double Write信息

系统相关:change buffer

生产中设置建议

5.7 中建议:设置共享表空间2-3个,大小建议512M或者1G,最后一个定制为自动扩展。

8.0 中建议:设置1个就ok,大小建议512M或者1G

c.共享表空间管理

查看共享表空间

select @@innodb_data_file_path;

ibdata1文件,默认初始大小12M,不够用会自动扩展,默认每次扩展64M

查看共享表空间每次扩展大小

select @@innodb_autoextend_increment;

设置方法

方法1:初始化之前设置共享表空间

(生产中建议方法)

在配置文件中写入共享表空间设置

vim /etc/my.cnf

#[mysqld]中添加参数
innodb_data_file_path=ibdata1:100M;ibdata2:100M;ibdata3:100M:autoextend

初始化数据库

mysqld --initialize-insecure --user=mysql --basedir=/data/app/mysql --datadir=/data/3306/data

启动数据库

/etc/init.d/mysqld start

方法2:已运行的数据库上扩展多个ibdata文件

先查看共享表空间实际大小

ls -lh ibdata1 

配置文件设定为和实际大小一致

vim /etc/my.cnf

#[mysqld]中添加参数
innodb_data_file_path=ibdata1:76M;ibdata2:100M;ibdata3:100M:autoextend

重启数据库生效

d,独立表空间

概念

5.6版本及之后版本中,针对用户数据,单独的存储管理。存储表的数据行和索引。

查看默认表空间模式

select @@innodb_file_per_table;

1代表独立表空间

0代表共享表空间模式

切换表空间模式

临时:

mysql> set global innodb_file_per_table=0;

永久:

vim /etc/my.cnf
innodb_file_per_table=1

利用独立表空间进行表的快速迁移

1. 锁定源端要迁移的表 ,并查看建表语句

lock tables test.t100w read;
show create table test.t100w;

2. 目标端创建所对应的库和空表

create database test charset=utf8mb4;
CREATE TABLE `t100w` (
  `id` int(11) DEFAULT NULL,
  `num` int(11) DEFAULT NULL,
  `k1` char(2) DEFAULT NULL,
  `k2` char(4) DEFAULT NULL,
  `dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3. 目标端利用数据库命令单独删除空的表空间文件

(保留要迁移表的frm,ibdata1中关于要迁移表的系统数据)

alter table test.t100w discard tablespace;

4. 拷贝源端ibd文件到目标端目录,并设置权限

cp /data/3306/data/test/t100w.ibd /data/3307/data/test/
chown -R mysql.mysql /data/*

5. 目标端导入表空间

alter table test.t100w import tablespace;

6. 查看是否导入成功

select count(*) from test.t100w;

e.undo表空间管理

undo表空间作用

用来作撤销工作

查看undo文件个数

select @@innodb_undo_tablespaces; 

存储位置

5.7版本,默认存储在共享表空间中(ibdataN)。8.0版本以后默认就是独立的(undo_001-undo_002)。

生产建议

5.7版本后,将undo手工进行独立

查看undo配置参数

SELECT @@innodb_undo_tablespaces;     
#打开独立undo模式,并设置undo的个数(一般设置为3-5个)。
SELECT @@innodb_max_undo_log_size;               
#undo日志的大小,默认1G。
SELECT @@innodb_undo_log_truncate;               
#开启undo自动回收的机制(undo_purge)。
SELECT @@innodb_purge_rseg_truncate_frequency;  
 #触发自动回收的条件,单位是检测次数。

MySQL 5.7 undo表空间配置步骤

注意:undo表空间只能在初始化的时候设置独立

第一步:备份数据库库

mysqldump -uroot -poldboy123  -A > /tmp/backup.sql

第二步:停止数据库服务并删除数据目录

/etc/init.d/mysqld stop

 rm -rf /data/3306/data/*

第三步:修改配置文件,添加参数

vim /etc/my.cnf

[mysqld]
user=mysql
basedir=/data/app/mysql
datadir=/data/3306/data
socket=/tmp/mysql.sock
port=3306
secure-file-priv=/tmp
innodb_undo_tablespaces=3          #打开独立undo模式并设置undo文件个数
innodb_max_undo_log_size=2G     #设置undo日志文件大小,默认是1G
innodb_undo_log_truncate=ON         #开启自动回收机制(通过undo purge线程)
innodb_purge_rseg_truncate_frequency=64      #发出自动回收条件,单位是回收次数
[mysql]
socket=/tmp/mysql.sock
prompt=5.7 [d]>

第四步:重新初始化数据库,使配置生效

mysqld --initialize-insecure --user=mysql --basedir=/data/app/mysql --datadir=/data/3306/data

第五步:启动数据库

/etc/init.d/mysqld start

第六步:查看是否配置成功

ll /data/3306/data/undo00*
-rw-r----- 1 mysql mysql 10485760 May  7 15:39 /data/3306/data/undo001
-rw-r----- 1 mysql mysql 10485760 May  7 15:39 /data/3306/data/undo002
-rw-r----- 1 mysql mysql 10485760 May  7 15:39 /data/3306/data/undo003

第七步:恢复数据

mysql -uroot -poldboy123 </tmp/back.sql

f.临时表空间管理

作用: 存储临时表。

管理

查询

select @@innodb_temp_data_file_path;

设置(修改配置文件)

vim /etc/my.cnf
#[mysqld]中添加参数
innodb_temp_data_file_path=ibtmp1:12M;ibtmp2:128M:autoextend:max:500M
                                                  #自动增长,最大增长到500M

/etc/init.d/mysqld restart

建议数据初始化之前设定好,一般2-3个,大小512M-1G

②、事务日志

a. redo log 重做日志

文件位置

/data/3306/data/ib_logfile0~ib_logfileN

(数据路径下)

功能

用来存储,MySQL在做修改类(DML)操作时的《数据页变化》过程及版本号(LSN),属于物理日志。

默认两个文件存储redo,是循环覆盖使用的。

日志优先写(WAL(write ahead log)),MySQL保证日志优先于数据写入磁盘

生产建议

大小:512M-4G

组数:2-4组

管理

查看redo log文件配置

show variables like '%innodb_log_file%';

控制参数

innodb_log_file_size=50331648      # 设置文件大小
innodb_log_files_in_group=2        # 设置文件个数
innodb_log_group_home_dir=./       # 设置存储位置

配置

vim  /etc/my.cnf 
# 添加参数:
[mysqld]
innodb_log_file_size=100M
innodb_log_files_in_group=3

/etc/init.d/mysqld restart

b. undo logs 回滚日志

文件位置:(5.7 默认位置)

ibdataN

ibtmp1

参数

innodb_rollback_segments=128   # 回滚段的个数

功能

用来存储回滚日志,可以理解为记录了每次操作的反操作,属于逻辑日志

1. 使用快照功能 提供InnoDB多版本并发读写。

2. 通过记录的反操作,提供回滚功能。

③、其他结构

a. ib_buffer_pool

文件位置

/data/3306/data

(数据路径下)

作用

缓冲和缓存,用来做“热”(经常查询或修改)数据页,减少物理IO。

当关闭数据库的时候,缓冲和缓存会失效。

5.7版本中,MySQL正常关闭时,会将内存的热数据存放(流方式)至ib_buffer_pool。

下次重启直接读取ib_buffer_pool加载到内存中。

b. Double Write buffer

文件位置

5.7 默认在ibdataN中,8.0.20以后可以设置为独立

作用

MySQL,最小IO单元page(16KB),OS中最小的IO单元是block(4KB)

为了防止出现以下问题:

数据页写入不完整

2、内存

①、innodb buffer pool(IBP)

作用

用来缓冲或缓存MySQL的数据页和索引页,是MySQL中最大的,最重要的内存区域

管理

查询

select @@innodb_buffer_pool_size;

默认大小128M

设置

临时设置

set global innodb_buffer_pool_size=268435456;

重新登录mysql生效

永久设置

vim /etc/my.cnf

#添加参数
innodb_buffer_pool_size=256M

重启生效

生产建议

设置为物理内存的50%-80%

②、innodb_log_buffer (ILB)

作用

用来缓冲 redo log日志信息。

管理

查询

select @@innodb_log_buffer_size;

设置

vim /etc/my.cnf

#[mysqld]中添加参数
innodb_log_buffer_size=512M

重启生效: /etc/init.d/mysqld restart

生产建议

和innodb_log_file_size有关,设置为前诉的1-N倍

(三)、innodb核心特性—事务支持

1、事务概念

伴随着交易类的业务出现的工作模式

数据库为了保证线上交易的和谐,加入了事物的工作机制

2、事务的ACID特性

A:原子性

不可再分性:一个事务生命周期中的DML语句,要么全成功,要么全失败,不可以出现中间状态

C:一致性

事务发生前、中、后数据都最终保持一致

I:隔离性

某个事务操作数据行时,不会受到其他事务的影响

D:持久性

一旦事务提交,永久生效(落盘)

3、事务的生命周期

标准(显示)的事务控制语句

开启事务

begin;

提交事务

commit;

回滚事务

rollback;

事务的完整生命周期演示

mysql> use world
mysql> begin;
mysql> delete from city where id=1;
mysql> update city set countrycode='CHN' where id=2;
mysql> commit;
mysql> begin;
mysql> select * from city limit 10;
mysql> update city set countrycode='AFG' where id=2;
mysql> delete from city where id=3;
mysql> rollback;

4、MySQL的自动提交机制

作用

在没有显示的使用begin语句的时候,执行DML,会在DML前自动添加begin,并在DML执行后自动添加commit

参数

select @@autocommit;

1代表开启

0代表关闭

设置

临时关闭

set global autocommit=0;

重新登录数据库生效

永久关闭

vim /etc/my.cnf
#[mysqld]中添加
autocommit=0

重启数据库生效

建议

频繁事务业务场景中,关闭autocommit。或者每次事务执行时都是显示的begin和commit;

5、隐式提交和隐式回滚

隐式提交

begin 
a
b
begin

SET AUTOCOMMIT = 1

导致提交的非事务语句:

DDL语句: (ALTER、CREATE 和 DROP)

DCL语句: (GRANT、REVOKE 和 SET PASSWORD)

锁定语句:(LOCK TABLES 和 UNLOCK TABLES)

导致隐式提交的语句示例:

TRUNCATE TABLE

LOAD DATA INFILE

SELECT FOR UPDATE

隐式回滚

会话窗口被关闭。

数据库关闭 。

出现事务冲突(死锁)。

5、事务的隔离级别

作用

实现事务工作期间的“读”隔离

级别类型

select @@transaction_isolation;

RU : READ-UNCOMMITTED 读未提交

说明

可以读取到事务未提交的数据

隔离级别

隔离级别最低,隔离性差

现象

脏读(当前内存读),不可重复读,幻读

RC : READ-COMMITTED 读已提交

说明

可以读取到事务已提交的数据

隔离级别

隔离性一般

现象

可以避免脏读,会出现不可重复读,幻读

RR : REPEATABLE-READ 可重复读

说明

事务A在读到一条数据之后,此时事务B对该数据进行了修改并提交,那么事务A再读该数据,读到的还是原来的内容

隔离级别

隔离性较好

现象

防止脏读,不可重复读,有可能出现幻读问题

SR : SERIALIZABLE 可串行化

说明

事务与事务之间串行工作

隔离级别

隔离性最好

隔离级别越高,并发性越低

(四)、事务工作流程原理(ACID特性如何保证)

1、名词介绍

重做日志(redo log)

ib_logfile0~N 默认大小48M , 轮询使用,存储数据页变化的日志

日志缓冲区(redo log buffer)

redo log内存区域

前滚日志(undo)

5.7默认放在ibdataN,可以配置为独立,默认大小128M,存储回滚信息

表空间数据文件

表的ibd文件 : 存储数据行和索引

数据缓冲区(InnoDB buffer pool)

缓冲区池,数据和索引的缓冲

日志序列号(LSN)

存在于磁盘数据页(ibd文件的page),redo log文件(ib_logfile),Innodb_buffer_pool中的数据页,redo log buffer中

数据库宕机启动时对比 flush_log LSN和 CKPT LSN ,如 flush_log LSN > CKPT LSN 则CR

MySQL 每次数据库启动,都会比较磁盘数据页和redolog的LSN,必须要求两者LSN一致数据库才能正常启动

指标查看: show engine innodb statusG

Log sequence number 3487050

Log flushed up to 3487050

Pages flushed up to 3487050

Last checkpoint at 3487041

日志优先写(WAL)

redo log日志文件优先于数据页写入磁盘

脏页(Dirty Page)

内存脏页,数据页在内存中发生了修改,没写入到磁盘前,我们将之称为脏页

检查点(CheckPoint)

检查点,就是将脏页刷写到磁盘的动作

事务ID号(TXID)

InnoDB会为每一个事务生成一个6字节的事务号,伴随着整个事务的生命周期

回滚指针(DB_ROLL_PTR)(7字节)

用来找到undo日志信息,

rollback 时,会使用 undo 日志回滚已修改的数据。

DB_ROLL_PTR指向了此次事务的回滚位置点

(五)、InnoDB事务工作流程

redo工作流程

1. 用户发起update事务语句,将磁盘数据页(page100,A=1,LSN=1000)加载到内存(buffer_pool)缓冲区。

2. 在内存中发生数据页修改(A=1改成A=2),形成脏页,更改中数据页的变化,记录到redo buffer中,加入1000个字节日志。LSN=1000+1000=2000。

3. 当commit语句执行时,基于WAL机制,等到redo buffer中的日志完全落盘到ib_logfileN中,commit正式完成。

4. ib_logfileN中记录了一条日志。内容:page100数据页变化+LSN=2000。

情景: 当此时,redo落地了,数据页没有落地,宕机了。

1. MySQL CR(自动故障恢复)工作模式,启动数据库时,自动检查redo的LSN和数据页LSN。

2. 如果发现redoLSN>数据页的LSN ,加载原始数据页+变化redo指定内存。使用redo重构脏页(前滚)。

3. 如果确认此次事务已经提交(commit标签),立即触发CKPT动作,将脏页刷写到磁盘上。

补充一点:

MySQL有一种机制,批量刷写redo的机制。会在A事务commit时,顺便将redo buffer中的未提交的redo日志也一并刷到磁盘。

为了区分不同状态的redo,日志记录时,会标记是否COMMIT。

07e04a6fa31ad36090d1953d4aa11e86.png

undo工作流程

undo log 回滚日志如何应用

1. 事务发生数据页修改之前,会申请一个undo事务操作,保存事务回滚日志(逆向操作的逻辑日志)。

2. undo写完之后,事务修改数据页头部(会记录DB_TRX_ID+DB_ROLL_PTR)

这个信息也会被redo 记录。

情景1

当执行rollback命令时。根据数据页的DB_TRX_ID+DB_ROLL_PTR信息,找到undo日志,进行回滚

情景2

begin;

update t1 set A=2 where A=1;

宕机。

假设: undo 有 , redo没有

启动数据库时,检查redo和数据页的LSN号码。发现是一致的。

所以不需要进行redo的前滚,此时也不需要回滚。undo信息直接被标记为可覆盖状态。

假设:undo 有,redo也有(没有commit标签。)

1. MySQL CR(自动故障恢复)工作模式,启动数据库时,自动检查redo的LSN和数据页LSN。

2. 如果发现redoLSN>数据页的LSN ,加载原始数据页+变化redo指定内存。使用redo重构脏页(前滚)。

3. 如果确认此次事务没有commit标记,立即触发回滚操作,根据DB_TRX_ID+DB_ROLL_PTR信息,找到und回滚日志,实现回滚。

以上流程被称之为InnoDB的核心特性:自动故障恢复(Crash Recovery)。先前滚再回滚,先应用redo再应用undo。

21befc81a2c43005d9ff53bd9cdfa74c.png

doublewrite工作流程

数据在写入磁盘前,会将数据分两次,每次1M先写入到DWB中,如果2M写入成功,数据则从buffer pool中写入到磁盘,2M数据写入到磁盘后,之后的数据也会先将2M覆盖写入到DWB中,写入成功后再将从buffer pool中写入到磁盘中,以此类推,直至将数据全部写完到磁盘。

(六)、MySQL锁机制(I的特性保证)

锁机制:写的隔离

1、作用

保证事务之间的隔离性,也保证也数据的唯一性

保证资源不会被争用,锁是属于组员的,不是某个事务的特性

每次事务需要资源时,需要申请持有资源的锁

2、锁的分类

按保护的资源分类

保护内存资源

(latch 闩锁)

rwlock(读写锁)

mutex(内存页锁)

保护元数据

(MDL (metadata lock)元数据锁)

table lock(表级锁)

添加表锁命令

lock table t1 read ;

表锁触发条件

mysqldump、XBK(PBK):备份非InnoDB数据时,触发FTWRL全局锁表(Global)。

row lock(行锁)

record lock(记录锁):在聚簇索引加锁。RC级别只有record lock

GAP lock(间隙锁):在辅助索引间隙加锁。RR级别存在,防止幻读

Next-lock(下一键锁):GAP+record。RR级别存在,防止幻读

按功能性分类

IS(意向共享锁)

S(共享锁)

IX(意向排它锁)

X(排它锁)

按类型

乐观锁

乐观锁认为一般情况下数据不会造成冲突,

所以在数据进行提交更新时才会对数据的冲突与否进行检测。

如果没有冲突那就OK;

如果出现冲突了,则返回错误信息并让用户决定如何去做

悲观锁

悲观锁,正如其名,它指的是对数据被外界(包括当前系统的其它事务,

以及来自外部系统的事务处理)修改持保守态度,

因此,在整个数据处理过程中,将数据处于锁定状态

(七)、MVCC(多版本并发控制)

作用

1. MVCC采用乐观锁机制,实现非锁定读取。

2. 在RC级别下,事务中可以立即读取到其他事务commit过的readview(版本号集合)

3. 在RR级别下,事务中从第一次查询开始,生成一个一致性readview,直到事务结束

原理

MVCC的实现,通过保存数据在某个时间点的快照来实现的。

这意味着一个事务无论运行多长时间,在同一个事务里能够看到数据一致的视图。

根据事务开始的时间不同,同时也意味着在同一个时刻不同事务看到的相同表里的数据可能是不同的。

五、存储引擎核心参数

(一)、双一标准

redo刷写参数

select @@innodb_flush_log_at_trx_commit

0:每秒刷新redo buffer到OS cache,再fsync()到磁盘

异常宕机时,会有可能导致丢失1s内的事务

1:在每次事务提交时,会立即刷新redo buffer到磁盘,commit才能成功

2:每次事务提交,都立即刷新redo buffer到OS cache,再每秒fsync()到磁盘

异常宕机时,会有可能会丢失1s内的事务

redo buffer刷写还和操作系统缓存机制有关,所以刷写策略可能和

innodb_flush_method参数有一定关系

binlog cache 刷写参数

select @@sync_binlog=1;

1:每次事务提交,都立即刷写binlog cache 中的日志到磁盘

0:每次提交事务,先将binlog cache 中的日志写到OS cache 中,在写入磁盘

(二)、innodb_flush_method

1、作用

控制MySQL刷写磁盘时,是否使用系统内存

innodb_flush_method=fsync/O_DIRECT/O_DIRECT/O_SYNC

fsync 模式

buffer pool的数据写磁盘的时候,需要先经历os cache,然后再写到磁盘

redo buffer 的数据写磁盘的时候,需要先经历os cache,然后再写到磁盘

O_DSYNC 模式

buffer pool的数据写磁盘的时候,需要先经历os cache,然后再写到磁盘

redo buffer 的数据写磁盘的时候,直接写到磁盘,跨过OS Cache

O_DIRECT 模式

buffer pool的数据写磁盘的时候,直接写到磁盘,跨过 OS Cache

redo buffer 的数据写磁盘的时候,需要先经历os cache,然后再写到磁盘

(三)、innodb_buffer_pool_size

作用

数据缓冲区的总大小。缓冲数据页和索引页。是MySQL最大的内存区域

生产建议

75%以下,按需调配

修改方式

1、临时修改

set global innodb_buffer_pool_size=402653184;

重新登录生效

2、永久修改

vim /etc/my.cnf

#[mysqld]中添加
innodb_buffer_pool_size=256M;

重启数据库生效

特点:

1、压缩比15倍以上(相比于innodb)

2、插入数据新能25倍(相比于innodb)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值