Mysql学习

一:基础篇

MYSQL概述,SQL, 函数,约束,多表查询,事务

二:进阶篇

存储引擎,索引,SQL优化,视图/存储过程/触发器, 锁,  InnoDB引擎,  MYSQL管理

三:运维篇

日志,主从复制,分库分表,读写分离

四:其他

基础篇: MYSQL概述,SQL, 函数,约束,多表查询, 事务

1. mysql概述

关系型数据库管理系统,开源,企业版,社区版 
版本: 5.x 、 6.x 、 7.x 、 8.x
常用工具:sqlyog  navicat  datagrip  dbeaver

2. DDL语句

2.1 常用语句:

mysql -u root -p    -- 使用root用户登录mysql
select version();    -- 查询mysql版本号 5.7.44-log
show databases; -- 查询数据库
create database my_db; -- 创建数据库
drop database my_db; -- 删除数据库
show databases;  -- 查询所有数据库
show tables;  -- 查询当前数据库所有表
show create table myuser2; -- 查询表创建sql
select database() -- 查询当前数据库
desc my_db1.myuser -- 查询当前表结构相关信息
alert table emp add nickname varchar(64) comment '昵称';  -- 给表添加字段
alert table emp modify nickname varchar(128) comment '昵称1'  -- 修改表字段类型.
alert table mep change nickname username varchar(256) comment '昵称'  -- 修改表字段名称及类型.
alert table emp drop username;  -- 删除字段
alert table emp rename to employee;  -- 修改表名
drop table emp;  -- 删除表
drop table if exists emp;
truncate table emp;  -- 删除指定表,并重新创建该表
set global validate_password_policy = 0;  --  设置mysql密码校验规则等级  0-low  1-middle  2-high
set global validate_password_length = 4;  --  设置密码长度为>=4位

2.2 数据类型

数值类型 2.字符串类型 3.日期时间类型

2.2.1 数值类型
    id int
    age  tinyint unsigned 无符号的数字类型
    score double(4,2)   4代表整体长度,2代表小数点后2位
2.2.2 字符串类型
    char(10)  (定长字符串-性能较高)10个字符         gender char(1)  性别    idcard char(18)
    varchar(128) (变长字符串-性能较差) 128个字符串   username varchar(64) 姓名
2.2.3 日期时间类型
    DATE -  YYYY-MM-DD 日期值    birthday (生日)- date  entrydate(入职时间)  date
    TIME -  HH:MM:SS  时间值或持续时间
    year -  YYYY  年份值
    *** DATETIME -    YYYY-MM-DD HH:MM:SS 日期+时间,这个用的多些
    TIMESTAMP -  YYYY-MM-DD HH:MM:SS 日期+时间  只能到 2023-01-19 03:14:07

3. DML语句:

insert update delete

4. DQL语句:

4.1 逻辑运算符

> >= < <= = <>或!=
between . and. (左小右大,含最小最大值)
in(...)
ike 占位符 _ 匹配单个字符 % 匹配任意字符
is null
4.2 逻辑运算符
and 或 &&
or  或 ||
not 或 !
4.3 聚合函数
4.3.1
null值是不参与所有聚合函数运算的
count  -统计数量
max    - 最大值
min    - 最小值
avg    - 平均值
sum    - 求和
SELECT * FROM my_db1.myuser;
select count(1) from my_db1.myuser;
select max(age) from my_db1.myuser;
select min(age) from my_db1.myuser;
select avg(age) from my_db1.myuser;
select sum(age) from my_db1.myuser;
4.3.2 分组 group by
select gender, count(1) from myuser group by gender;
select gender, avg(age) from myuser where age < 10 group by gender;
select gender, count(1) from myuser group by gender having count(1) > 2;
4.3.3 排序查询
select * from myuser order by age asc ;  -- 按照年龄升序 asc 默认值,可以不写
select * from myuser order by age desc ; -- 按照年假进行降序
select * from myuser order by age desc , gender desc; -- 按照年假进行降序,如果年龄相同,在按照性别进行降序排序
4.3.4 分页查询
方言:  limit (mysql)  rownum (oracle嵌套)
select * from myuser limit 0, 2;  -- 第1页,每页展示2条
select * from myuser limit 2      -- 上面可以省略为此,如果从第1页开始的
4.3.5 DQL执行顺序
    SELECT
        字段列表      ⑦
    FROM
        表名称列表    ①
    WHERE
        条件列表      ②
    GROUP BY
        分组字段列表   ③
    HAVING
        分组后条件列表 ④
    ORDER BY
        排序字段列表   ⑤
    LIMIT
        分页参数      ⑥

5. DCL语句

SELECT USER(); -- 查询当前用户
CREATE USER 'username'@'localhost' identified  by 'password';  -- 创建用户 username,只能够在当前主机localhost访问,密码为password
CREATE USER 'username'@'%' identified  by 'password'; -- 创建用户 username,可以在任意主机访问数据库, 密码是 password
ALTER USER 'username'@'%' identified with mysql_native_password by 'password1';  -- 修改用户 'username'@'%'的访问密码为 password1
create user 'chenzhen'@'%' identified with mysql_native_password by 'password';  -- 创建用户chenzhen,密码为password,可以在任意主机访问该数据库
grant all on *.* to 'chenzhen'@'%';  -- 分配所有权限
DROP USER 'username'@'localhost';  --  删除 'username'@'localhost' 用户
-- 权限控制
   ALL,ALL PRIVILEGES  -- 所有权限
   SELECT  -- 查询权限
   INSERT  -- 插入权限
   UPDATE  -- 修改权限
   DELETE  -- 删除权限
   ALTER   -- 修改表
   DROP    -- 删除数据库/表/视图
   CREATE  -- 创建数据库/表

   show grants for 'root'@'%';   -- 查询权限
   grant all on itcast.* to 'root'@'%';  -- 授予权限
   revoke all on itcast.* from 'root'@'%'; -- 撤销权限

6. 函数

字符串函数,数值函数,日期函数,流程函数

6.1 字符串函数

    concat(s1, s2,... sn) 字符串拼接,将s1,s2,...sn拼接成一个字符串
    lower(str) 将字符串str全部转为小写
    upper(str) 将字符串str全部转为大写
    trim(str) 去除字符串头部和尾部的空格
    substring(str,start,len) 返回从字符串str从start位置起的len个长度的字符串
    lpad(str, n, pad) 左填充,用字符串pad对str的左边进行填充,达到n个字符串长度
    rpad(str, n, pad) 右填充,用字符串pad对str的右边进行填充,达到n个字符串长度
    select concat('hello',' mysql');    hello mysql
    select lower('HELLOW');             hellow
    select upper('hello');              HELLO
    select lpad('01',5,'-');            ---01
    select rpad('01',5,'-');            01---
    select trim( ' hell o ');           hell o
    select substring('Hello mysql', 1,5); Hello
    update myuser set worknum = lpad(worknum, 5, '0');  -- 把所有员工 工号补充为5位数,不足5位的前面加0

6.2 数字函数

   ceil(x) 向上取整
   floor(x) 向下取整
   mod(x,y) 返回 x/y的模
   rand()   返回0~1内的随机数
   round(x,y) 求参数x的四舍五入的值,保留y位小数
    select ceil(1.5);        2
    select ceil(1.0);        1
    select ceil(1.1);        2
    select floor(1.5);       1
    select floor(1.0);       1
    select floor(1.1);       1
    select mod(7,4);         3
    select rand();           0.583896713875138
    select round(2.344,2);  2.34
    select round(2.345,2);  2.35
    select lpad(round(rand()*1000000,0),6,'0');    806416   086895   -- 生成一个随机的6位数验证码

6.3 日期函数

 curdate()    返回当前的日期
 curtime()    返回当前时间
 now()        返回当前日期+时间
 year(date)   获取指定date的年份
 month(date)  获取指定date的年份
 day(date)    获取指定date的日期
 date_add(date,interval expr type) 返回一个日期/时间值加上一个时间间隔expr后的时间值
 datediff(date1, date2)  返回起始时间date1和结束时间date2之间的天数  date1 - date2
 select curdate();    2024-12-10
 select curtime();    10:32:34
 select  now();       2024-12-10 10:32:51
 select year(now());  2024
 select month(now()); 12
 select day(now());   10

 select date_add(now(), INTERVAL 10 day );  2024-10-20 10:35:50  往后推10天
 select date_add(now(), INTERVAL -10 day ); 2024-11-30 10:36:25  往前推10天
 select datediff('2021-11-11','2021-11-12 10:35:50');  -1    --  date1 -date2

 查询所有员工的入职天数,并根据入职天数倒叙排序
 select username,datediff(curdate(), entrydate)  as  entrydays from myuser order by entrydays desc;

6.4 流程控制函数

if(value, t, f)  如果value为true,则返回t,否则返回f
ifnull(value1,value2) 如果value1不为null,返回value1, 否则返回value2
case when [val1] then [res1] ... else[default] end 如果val1为true,返回res1,...否则返回default默认值
case [expr] when [val1] then [res1]...else [default] end 如果expr的值等于val1,返回res1,...否则返回default默认值
select if(true, 'ok','error');  ok
select ifnull('ok','error');   ok
select ifnull('','default');   空
select ifnull(null, 'default');  default
--  查询员工的工作地址, (北京,上海)展示为 ‘一线城市’, 其他城市 展示为 ‘二线城市’
select username,
        (case address
        when '北京' then '一线城市'
        when '上海' then '一线城市'
        else '二线城市'
        end ) as ‘工作地址’
       from myuser;

-- 针对学员成绩: >= 85 展示 ‘优秀’ >= 60展示 ‘及格’ 否则展示 ‘不及格’
select id, name,
       ( case when math >= 85 then '优秀' when math >= 60 then '及格' else ‘不及格’ end ) as '数学成绩',
       ( case when english >= 85 then '优秀' when english >= 60 then '及格' else ‘不及格’ end ) as '英语成绩'
from score;

7. 约束

约束作用于表中字段上的规则,用于限制存储在表中的数据。 目的: 保证数据库中数据的正确性,有效性和完整性

非空约束: NOT NULL             限制该字段的数据不能为null
唯一约束: UNIQUE               保证该字段的所有数据都是唯一,不能重复的
主键约束: PRIMARY KEY          主键是一行数据的唯一标识,要求非空且唯一
默认约束: DEFAULT              保存数据时,如果未指定该字段的值,则采用默认值
外键约束: FOREIGN KEY          用来让2张表的数据之间建立联系,保证数据的一致性和完整性
检查约束(8.0.16版本之后) CHECK   保证字段值满足某一个条件

create table myuser2 (
    id int primary key auto_increment comment '主键',
    name varchar(10) not null unique comment '姓名',
    age int comment '年龄',  -- 检查约束 8.0.16版本之后
    -- age int check ( age > 0 && age <= 120 ) comment '年龄',  -- 检查约束 8.0.16版本之后
    status char(1) default '1' comment '状态,默认1',
    gender char(1) comment '性别'
) comment '用户表';

添加外键 2张表, 删除/更新行为 级联操作
删除/更新行为以下:
1. NO ACTION 和  RESTRICT  在父表中删除/更新记录时, 首先检查该记录是否有外键, 有则不允许删除/更新
2. CASCADE 级联操作         --------------------------------------------有则也更新/删除外键在子表中的记录。
3。SET NULL               ---------------------------------------------有则设置子表中该外键为值为null (这就要求该外键允许为null)
4. SET DEFAULT           ---------------------------------------------有则子表将外键列设置为一个默认值(Innodb不支持)
alter table myuser2 add constraint fk_emp_dept_id foreign key (dept_id) references dept(id)  on update CASCADE on delete cascade ;
alter table myuser2 drop foreign key fk_emp_dept_id;   -- 删除外键

insert into myuser2(name, age, status, gender)  values ('陈振',32,'1','男');
insert into myuser2(name, age, gender)  values ('陈振2',32,'男');
insert into myuser2(name, age, status, gender)  values ('陈振3',32,'','女');
insert into myuser2(name, age, status, gender)  values ('陈振4',32,null,'女');

8. 多表查询

多表关系,多表查询概述,内连接,外连接,自连接,子查询,多表查询案例

8.1 多表关系

   一对多(多对一):    实现:在多的一方建立外键,指向一的一方的主键
   多对多:            实现:建立第三张中间表,中间表至少包含2个外键,分别关联2方主键
    一对一:            实现:在任意一方加上外键,关联另一方的主键,并且设置外键为唯一的(unique)。 经常做单表的拆分

8.2 多表查询

    -- 笛卡尔积: 两个集合A,B所有的组合情况  A*B   --> 在进行多表查询时,需要消除无效的笛卡尔积
    select * from emp, dept where emp.dept_id = dept.id;
    -- 多表查询分类:
        -- 1.连接查询:
            -- 1.1 内连接: 相当于查询A,B交集部分数据
            -- 1。2 外连接:
                -- 1.2.1 左外连接: 查询左表所有的数据,以及两张表交集部分数据
                -- 1.2.2 右外连接: 查询右表所有数据,以及两张表交集部分数据
            -- 1.3 自连接:当前表与自身的连接查询,自连接必须使用表别名
            -- 1.4 联合查询: 把2次或多次查询的结果进行合并
        -- 2.子查询: sql中嵌套select语句,称为嵌套查询,又称子查询

8.3 内连接:

相当于查询A,B两张表的交集数据
    -- 隐式内连接:  select 字段列表 from 表1, 表2 where 条件...;
    -- 显示内连接:  select 字段列表 from 表1  [inner] join 表2 on 连接条件...;
    select emp.name, dept.name from emp, dept where emp.dept_id = dept.id;  -- 隐式内连接:  查询每一个员工的姓名, 及关联的部门的名称
    select e.name, d.name from emp e, dept d where e.dept_id = d.id;
    select e.name, d.name from emp e inner join dept d on e.dept_id = d.id; -- 显式内连接

8.4 外连接

8.4,1 左外连接
    	相当于查询表1(左表)的所有数据,包含表1和表2交集部分的数据  ** 用的多些
        --  查询emp表所有的数据, 和对应的部门信息
        select e.*, d.name from emp e left join dept d on e.dept_id = d.id;
        select e.*, d.name from emp e left outer join dept d on e.dept_id = d.id;  -- outer关键字可以省略
8.4,2 右外连接
		相当于查询表2(右表)的所有数据,包含表1和表2交集部分的数据   ** 右外可以转换为左外连接
        --  查询dept表所有的数据, 和对应员工信息
         select d.*, e.name from emp e right join dept d on e.dept_id = d.id;   -- outer关键字可以省略

8.5 自连接

		可以是内连接查询,也可以是外连接查询。
        -- 查询员工及所属领导的名字 - 内连接  只查询表a,b交集的部分
        select e.name, e1.name from emp e, emp e1 where e.manage_id = e1.id;
        -- 查询所有所有员工 emp及其领导名字 emp, 如果员工没有领导,也需要查询出来 -- 外连接
        select e.name as '员工姓名', e1.name as '领导名字' from emp e  left join emp e1 on e.manage_id = e1.id;

8.6 联合查询

    union, union all 就是把多次查询的结果合并起来,形成一个新的查询结果集  A+B  形成all,
    union all 直接将查询的结果进行合并
    union 将查询结果合并后再进行去重处理
    -- 对于联合查询,多张表的列数必须保持一致,字段类型也需要保持一致
        select 字段列表 from 表A...
        union[all]
        select 字段列表 from 表B...
        -- 将薪资低于5000的员工, 和年龄大于50岁的员工全部查询出来
        select * from emp where salary < 5000
        union all
        select * from emp where age > 50;

8.7 子查询:

	sql中嵌套select语句,称为嵌套查询,又称子查询
    子查询外部的语句可以是insert/uodate/delete/select 的任何一个
    根据子查询结果不同,分为:
        ①. 标量子查询: 子查询的结果为单个值
        ②. 列子查询:  子查询的结果为一列(可以是多行)
        ③. 行子查询:  子查询结果为一行
        ④. 表子查询:  子查询结果为多行多列
    根据子查询位置,分为: WHERE之后, FROM之后,SELECT之后
8.7.1 标量子查询:
 子查询返回的结果是单个值 (数字,字符串,日期等),最简单的形式,这种子查询称为标量子查询
   常用的操作符: = <> > >= < <=
   ①查询’销售部‘所有员工信息
   select * from emp where dept_id = (select id from dept where name = '销售部');
   ②查询'方东白'入职之后的员工信息
   select * from emp where entrydate > (select entrydate from emp where name = '方东白');
8.7.2 列子查询:
子查询返回的结果是一列(可以是多行)一列多行
        常用的操作符: IN , NOT IN , ANY , SOME , ALL
            IN       在指定的集合范围之内, 多选一
            NOT IN   不在指定的集合范围之内
            ANY      子查询返回列表中,有任意一个满足即可
            SOME     与ANY等同,使用SOME的地方都可以使用ANY
            ALL      子查询返回列表的所有值都必须满足
        ①: 查询'销售部','市场部'的所有员工 (1列多行)
            select * from emp where dept_id in (select id from dept where name in ('销售部', '市场部'));
        ②: 查询比'财务部'所有人工资都高的员工信息
                第一步: 查询所有 ’财务部‘ 员工的工资
                select salary from emp where dept_id = (select id from dept where name  = '财务部');
                第二步:  比财务部所有人工资都高的员工信息
                 select * from emp where salary >  all(select salary from emp where dept_id = (select id from dept where name = '财务部’));
        ③:查询比 ‘研发部’其中任意一人工资高的员工信息
                select * from emp where salary > any(select salary from emp where dept_id = (select id from dept where name = '研发部'));
                select * from emp where salary > some(select salary from emp where dept_id = (select id from dept where name = '研发部'));
8.7.3 行子查询:
子查询结果为一行,(可以是多列)  一行多列
        常用的操作符:  = , <> , IN , NOT IN
        ①:查询与 '张无忌'的薪资及直属领导相同的员工信息
            -- 第一步: 查询‘张无忌’的薪资及直属领导 (字段1: ‘张无忌的薪资’ 字段2: 直属领导)
            select salary,manage_id from emp where name = '张无忌';
            -- 第二步:
            select * from emp where (salary, manage_id) = (select salary,manage_id from emp where name = '张无忌')
8.7.4 表子查询:

子查询返回的结果是多行多列
常用的操作符: IN
①: 查询与 ‘张无忌’,‘宋元桥’的职位和薪资相同的员工信息
select job, salary from emp where name = ‘张无忌’ or name = ‘宋元桥’; //多行
select * from emp where (job, salary) in (select job, salary from emp where name = ‘张无忌’ or name = ‘宋元桥’);
②: 查询入职日期是 ‘2024-12-10’之后的员工信息,及其部门信息
select * from emp where entrydate > ‘2024-12-10’; – 把这个查询结果作为一张表
select e., d. from (select * from emp where entrydate > ‘2024-12-10’) e left join dept d on e.dept_id = d.id;

8.8: 多表查询练习:

    ①; 查询员工的 姓名,年龄,职位,部门信息 (隐式内连接)
        select e.name, e.age, e.job, d.* from emp e , dept d where e.dept_id = d.id;
    ②: 查询年龄小于30岁的员工的姓名,年龄,职位 部门信息(显式内连接)
        select e.name, e.age, e.job, d.* from emp e inner join dept d on e.dept_id = d.id where e.age < 30
    ③:查询拥有员工的部门id,部门名称 (内连接: 查询的是两张表交集的部分)
        select distinct d.id, d.name from emp e , dept d where e.dept_id = d.id;
    ④:查询所有年龄大于40岁的员工,及其归属的部门名称; 如果员工没有分配部门,也需要查询出来。
        select e.*, d.name from emp e left join dept d on e.dept_id = d.id where e.age > 40;
     ⑤:查询所有员工的工资等级
        select e.*, s.grade, s.losal, s.hisal from emp e, salgrade s where e.salary >= s.losal and e.salary <= s.hisal;
        select e.*, s.grade, s.losal, s.hisal from emp e, salgrade s where e.salary between s.losal and s.hisal;
     ⑥:查询 '研发部' 所有员工的信息及工资等级
        select e.*, s.grade from emp e, salgrade s, dept d where e,dept_id = d.id and (e.salary between s.losal and s.hisal) and d.name = '研发部';
    ⑦:查询 '研发部' 员工的平均工资
        select avg(e.salary) from emp e, dept d where e.dept_id = d.id and d.name = '研发部';
    ⑧:查询工资比‘灭绝’高的员工信息;-- 子查询
        select e.* from emp e where e.salary > (select e1.salary from emp e1 where e1.name = '灭绝');
     ⑨:查询比平均工资高的员工信息
        select e.* from emp e where e.salary > (select avg(e1.salary) from emp e1);
    ⑩:查询低于本部门平均工资的员工信息
        select e.* from emp e where e.salary < (select avg(e1.salary) from emp e1 where e.dept_id = e1.dept_id);
    11: 查询所有的部门信息,并统计部门的员工人数
        select d.id, d.name, (select count(*) from emp e where e.dept_id = d.id) as ‘人数’ from dept d;
    12: 查询所有学生的选课情况,展示学生名称,学号,课程名称  多对多  表 student, course, student_course 中间表
        select s.name,s.no,c.name from student s,student_course sc,course c where s.id = sc.student_id and c.id = sc.course_id;

9 事务

事务简介, 事务操作, 事务四大特性, 并发事务问题, 事务隔离级别

9.1. 事务:

是一组操作的集合,他是不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作:要么同时成功,要么同时失效

9.2. 操作示例: 张三向李四转账1000元

    select * from account where name = '张三'
    update account set money = money -1000 where name = '张三';
    update account set money = money + 1000 where name = '李四';

    select @@autocommit;   -- 1:自动提交 0:手动提交  mysql支持,oracle不支持
    --  方式一: 手动提交事务
    set @@autocommit = 0;  -- 设置会话为手动提交
    commit;                -- 提交事务
    rollback;              -- 回滚事务

    -- 方式二: 显示开启事务
    start transaction 或 begin   -- 开启事务
        --- do things
    commit;                     -- 提交事务
    rollback;                   -- 回滚事务

9.3 事务四大特性ACID***:

	原子性, 一致性, 隔离性, 持久性
    ①: 原子性: Atommicity 事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
    ②: 一致性: Consistency 事务完成时,必须使所有的数据都保持一致状态
    ③: 隔离性: Isolation 数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境中运行。
    ④: 持久性: Durability 事务一旦提交或回滚,它对数据库中的数据的改变是永久的。

9.4.并发事务引发的问题: 脏读, 不可重复读, 幻读

    脏读:一个事务A读到另一个事务B还没有提交的数据。
    不可重复读: 一个事务A先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。
    幻读: (前后多次读取,数据总量不一致)一个事务按照条件查询数据时,没有对应的数据行, 但是在插入数据时,又发现这行数据已经存在,好像出现了幻读。

9.5 事务的隔离级别:

	√ 存在,有   X 不存在  TODO:这一块4,5重新梳理下, 后续锁完结后再来总结
    ①: Read uncommitted :                    脏读 √(存在)    不可重复读 √(存在)     幻读 √(存在)
    ②: Read committed: (Oracle默认隔离级别)  脏读 x(不存在)   不可重复读 √(存在)     幻读 √(存在)
    ③: Repeatable Read(mysql默认隔离级别)      脏读 x(不存在)   不可重复读 X(不存在)   幻读 √(存在,MYSQL采用MVCC机制解决了幻读的问题,MYSQL不存在幻读,意味着mysql查询两次查询结果相同)
    ④: Serializable:                         脏读 x(不存在)   不可重复读 X(不存在)   幻读 X(不存在)

    查询事务的隔离级别
    select @@transaction_isolation;
    设置事务的隔离级别
    set [session|grobal] transaction isolation level [read uncommited | read commited | repeatable read | serializable]
    -事务的隔离级别越高,数据越安全,但是性能越低。 反之易之- 权衡之

进阶篇: 存储引擎,索引,SQL优化,视图/存储过程/触发器, 锁, InnoDB引擎, MYSQL管理

10. 存储引擎

10.1 mysql体系结构

10.1.1 Mysql系统结构图

在这里插入图片描述
在这里插入图片描述
由上至下,我们可以MySQL的体系构架划分为:1.网络接入层 2.服务层 3.存储引擎层 4.文件系统层

网络接入层
提供了应用程序接入MySQL服务的接口。客户端与服务端建立连接,客户端发送SQL到服务端。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈振wx:zchen2008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值