未验证 提交 db81b992 编写于 作者: N Nliver 提交者: GitHub

docs(tianmu): update the docs of stonedb-5.7 (#489) (#492)

* git: update .gitignore

* docs(tianmu): update the docs of  Quick Depolyment

* docs(tianmu): update the docs of  Compile Methods

* docs(tianmu): update the docs of  Performance Test

* docs(tianmu): update the docs of Performance Tuning

* docs(tianmu): update the docs of Troubleshooting

* docs(tianmu): update the docs of FAQ
Co-authored-by: Nmergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
上级 ae8dc05a
......@@ -117,3 +117,4 @@ CTestTestfile.cmake
COPYING
.vs/
node_modules
website/.docusaurus
\ No newline at end of file
{
"position": 3.1,
"label": "Quick Deployment",
"collapsible": true,
"link": {
"type": "generated-index",
"slug": "/quick-deployment"
}
}
\ No newline at end of file
---
id: quick-deployment
sidebar_position: 3.1
id: quick-deployment-56
sidebar_position: 3.11
---
# Quick Deployment
# Quick Deploy StoneDB-5.6
## 1. Download the latest package
Click [here](https://static.stoneatom.com/stonedb-ce-5.6-v1.0.0.el7.x86_64.tar.gz) to download the latest installation package of StoneDB.
## **1. Download the latest package**
Click [here](https://static.stoneatom.com/stonedb-ce-5.6-v1.0.0.el7.x86_64.tar.gz) to download the latest installation package of StoneDB.
## **2. Upload and decompress the TAR package**
:::info
To simplify deployment, the installation package provided here is pre-compiled to include all required dependencies.
:::
## 2. Upload and decompress the TAR package
```shell
cd /
tar -zxvf stonedb-ce-5.6-v1.0.0.el7.x86_64.tar.gz
```
Upload the installation package to the directory. The name of the folder extracted from the package is /**stonedb56**.
## **3. Check dependencies**
You can uload the installation package to the server. The name of the folder extracted from the package is **stonedb56**. In this topic, **/stonedb56** is used as the installation package.
## 3. Check dependencies
```bash
cd /stonedb56/install/bin
ldd mysqld
......@@ -21,18 +24,18 @@ ldd mysql
```
If the command output contains keywords **not found**, some dependencies are missing and must be installed. <br />For example, `libsnappy.so.1 => not found` is returned:
- If your OS is Ubuntu, run the `sudo apt search libsnappy` command. The command output will inform you to install `libsnappy-dev`. For more details, see [Compile StoneDB on Ubuntu 20.04](../04-developer-guide/00-compiling-methods/compile-using-ubuntu2004.md).
- If your OS is RHEL or CentOS, run the `yum search all snappy` command. The command output will inform you to install **snappy-devel** and **snappy**. For more details, see [Compile StoneDB on CentOS 7](../04-developer-guide/00-compiling-methods/compile-using-centos7.md) or [Compile StoneDB on RHEL 7](../04-developer-guide/00-compiling-methods/compile-using-redhat7.md).
## **4. Start StoneDB**
- If your OS is Ubuntu, run the `sudo apt search libsnappy` command. The command output will inform you to install `libsnappy-dev`. For more details, see [Compile StoneDB on Ubuntu 20.04](../../04-developer-guide/00-compiling-methods/compile-using-ubuntu2004/compile-using-ubuntu2004-for-56.md).
- If your OS is RHEL or CentOS, run the `yum search all snappy` command. The command output will inform you to install **snappy-devel** and **snappy**. For more details, see [Compile StoneDB on CentOS 7](../../04-developer-guide/00-compiling-methods/compile-using-centos7/compile-using-centos7-for-56.md) or [Compile StoneDB on RHEL 7](../../04-developer-guide/00-compiling-methods/compile-using-redhat7/compile-using-redhat7-for-56.md).
## 4. Start StoneDB
Users can start StoneDB in two ways: manual installation and automatic installation.
### 4.1 Create an account.
### 4.1 Create an account
```bash
groupadd mysql
useradd -g mysql mysql
passwd mysql
```
### 4.2 Manually install StoneDB.
You need to manually create directories, and then initialize and start StoneDB.
### 4.2 Manually install StoneDB
You need to manually create directories, configure the parameter file, and then initialize and start StoneDB.
```shell
### Create directories
mkdir -p /stonedb56/install/data/innodb
......@@ -58,16 +61,19 @@ chown -R mysql:mysql /stonedb56/install/stonedb.cnf
### Start StoneDB
/stonedb56/install/bin/mysqld_safe --defaults-file=/stonedb56/install/stonedb.cnf --user=mysql &
```
### 4.3 Automatically install StoneDB.
### 4.3 Automatically install StoneDB
The process of executing the **reinstall.sh** script is to initialize and start the StoneDB.
```bash
cd /stonedb56/install
./reinstall.sh
```
The process of executing the script is to initialize and start the StoneDB.<br />Differences between **reinstall.sh** and **install.sh**:
:::info
Differences between **reinstall.sh** and **install.sh**:
- **reinstall.sh** is the script for automatic installation. When the script is being executed, directories are created, and StoneDB is initialized and started. Therefore, do not execute the script unless for the initial startup of StoneDB. Otherwise, all directories will be deleted and StoneDB will be initialized again.
- **install.sh** is the script for manual installation. You can specify the installation directories based on your needs and then execute the script. Same as **reinstall.sh**, when the script is being executed, directories are created, and StoneDB is initialized and started. Therefore, do not execute the script unless for the initial startup. Otherwise, all directories will be deleted and StoneDB will be initialized again.
## **5. Log in to StoneDB**
- **install.sh** is the script for manual installation. You can specify the installation directories based on your needs and then execute the script. Same as reinstall.sh, when the script is being executed, directories are created, and StoneDB is initialized and started. Therefore, do not execute the script unless for the initial startup. Otherwise, all directories will be deleted and StoneDB will be initialized again.
:::
## 5. Log in to StoneDB
```shell
/stonedb56/install/bin/mysql -uroot -p -S /stonedb56/install/tmp/mysql.sock
Enter password:
......@@ -94,7 +100,7 @@ mysql> show databases;
+--------------------+
7 rows in set (0.00 sec)
```
## **6. Stop StoneDB**
## 6. Stop StoneDB
```shell
/stonedb56/install/bin/mysqladmin -uroot -p -S /stonedb56/install/tmp/mysql.sock shutdown
```
\ No newline at end of file
---
id: quick-deployment-57
sidebar_position: 3.12
---
# Quick Deploy StoneDB-5.7
## 1. Download the installation package
Click [here](https://static.stoneatom.com/custom/stonedb-ce-5.7-v1.0.0.el7.x86_64.tar.gz) to download the latest installation package of StoneDB.
:::info
To simplify deployment, the installation package provided here is pre-compiled to include all required dependencies.
:::
## 2. Upload and decompress the TAR package
```shell
cd /
tar -zxvf stonedb-ce-5.7-v1.0.0.el7.x86_64.tar.gz
```
You can upload the installation package to the server. The name of the folder extracted from the package is **stonedb56**. In this topic, **/stonedb56** is used as the installation package.
## 3. Check dependencies
```shell
cd /stonedb57/install/bin
ldd mysqld
ldd mysql
```
If the command output contains keywords **not found**, some dependencies are missing and must be installed. <br />For example, `libsnappy.so.1 => not found` is returned:
- If your OS is Ubuntu, run the `sudo apt search libsnappy` command. The command output will inform you to install `libsnappy-dev`. For more details, see [Compile StoneDB on Ubuntu 20.04](../../04-developer-guide/00-compiling-methods/compile-using-ubuntu2004/compile-using-ubuntu2004-for-57.md).
- If your OS is RHEL or CentOS, run the `yum search all snappy` command. The command output will inform you to install **snappy-devel** and **snappy**. For more details, see [Compile StoneDB on CentOS 7](../../04-developer-guide/00-compiling-methods/compile-using-centos7/compile-using-centos7-for-57.md) or [Compile StoneDB on RHEL 7](../../04-developer-guide/00-compiling-methods/compile-using-redhat7/compile-using-redhat7-for-57.md).
## 4. Start StoneDB
Users can start StoneDB in two ways: manual installation and automatic installation.
### 4.1 Create an account
```shell
groupadd mysql
useradd -g mysql mysql
passwd mysql
```
### 4.2 Manually install StoneDB
You need to manually create directories, configure the parameter file, and then initialize and start StoneDB.
```shell
### Create directories.
mkdir -p /stonedb57/install/data
mkdir -p /stonedb57/install/binlog
mkdir -p /stonedb57/install/log
mkdir -p /stonedb57/install/tmp
mkdir -p /stonedb57/install/redolog
mkdir -p /stonedb57/install/undolog
chown -R mysql:mysql /stonedb57
### Configure my.cnf.
mv my.cnf my.cnf.bak
vim /stonedb57/install/my.cnf
[mysqld]
port = 3306
socket = /stonedb57/install/tmp/mysql.sock
basedir = /stonedb57/install
datadir = /stonedb57/install/data
pid_file = /stonedb57/install/data/mysqld.pid
log_error = /stonedb57/install/log/mysqld.log
innodb_log_group_home_dir = /stonedb57/install/redolog/
innodb_undo_directory = /stonedb57/install/undolog/
chown -R mysql:mysql /stonedb57/install/my.cnf
### Initialize StoneDB.
/stonedb57/install/bin/mysqld --defaults-file=/stonedb57/install/my.cnf --initialize --user=mysql
### Start StoneDB.
/stonedb57/install/bin/mysqld_safe --defaults-file=/stonedb57/install/my.cnf --user=mysql &
```
### 4.3 Automatically install StoneDB
The process of executing the **reinstall.sh** script is to initialize and start the StoneDB.
```shell
cd /stonedb57/install
./reinstall.sh
```
:::info
Differences between **reinstall.sh** and **install.sh**:
- **reinstall.sh** is the script for automatic installation. When the script is being executed, directories are created, and StoneDB is initialized and started. Therefore, do not execute the script unless for the initial startup of StoneDB. Otherwise, all directories will be deleted and StoneDB will be initialized again.
- **install.sh** is the script for manual installation. You can specify the installation directories based on your needs and then execute the script. Same as reinstall.sh, when the script is being executed, directories are created, and StoneDB is initialized and started. Therefore, do not execute the script unless for the initial startup. Otherwise, all directories will be deleted and StoneDB will be initialized again.
:::
### 5. Log in to StoneDB
```shell
cat /stonedb57/install/log/mysqld.log |grep passwd
[Note] A temporary password is generated for root@localhost: ceMuEuj6l4+!
/stonedb57/install/bin/mysql -uroot -p -S /stonedb57/install/tmp/mysql.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36-StoneDB-debug-log build-
Copyright (c) 2021, 2022 StoneAtom Group Holding Limited
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> alter user 'root'@'localhost' identified by 'stonedb123';
```
## 6. Stop StoneDB
```shell
/stonedb57/install/bin/mysqladmin -uroot -p -S /stonedb57/install/tmp/mysql.sock shutdown
```
\ No newline at end of file
......@@ -7,10 +7,10 @@ sidebar_position: 5.11
The method to compile StoneDB varies with the environment. Choose the compiling method that suits your environment.
- [Compile StoneDB on CentOS 7](compile-using-centos7.md)
- [Compile StoneDB on RHEL 7](compile-using-redhat7.md)
- [Compile StoneDB on Ubuntu 20.04](compile-using-ubuntu2004.md)
- [Compile StoneDB Using a Docker Container](compile-using-docker.md)
- [Compile StoneDB on CentOS 7](./compile-using-centos7/compile-using-centos7-for-57.md)
- [Compile StoneDB on RHEL 7](./compile-using-redhat7/compile-using-redhat7-for-57.md)
- [Compile StoneDB on Ubuntu 20.04](./compile-using-ubuntu2004/compile-using-ubuntu2004-for-57.md)
- [Compile StoneDB Using a Docker Container](./compile-using-docker.md)
{
"position": 5.12,
"label": "Compile StoneDB on CentOS7.x",
"collapsible": true
}
\ No newline at end of file
---
id: compile-using-centos7-foe-56
sidebar_position: 5.121
sidebar_position: 5.122
---
# Compile StoneDB for MySQL5.6 on CentOS 7
......
---
id: compile-using-centos7-for-57
sidebar_position: 5.122
sidebar_position: 5.121
---
# Compile StoneDB for MySQL5.7 on CentOS 7
......
......@@ -162,7 +162,7 @@ After the `make` commands are successful, you can choose either to compress the
[root@06f1f385d3b3 build]# tar -zcPvf /home/stonedb56.tar.gz /stonedb56/
```
### Directly use StoneDB in the container
You can refer to [Quick Deployment](.../../../../02-getting-started/quick-deployment.md) or the following code to deploy and use StoneDB in the container.
You can refer to [Quick Deployment](.../../../../02-getting-started/quick-deployment) or the following code to deploy and use StoneDB in the container.
```bash
[root@06f1f385d3b3 build]# cd /stonedb56/install/
......
{
"position": 5.13,
"label": "Compile StoneDB on RedHat7.x",
"collapsible": true
}
\ No newline at end of file
---
id: compile-using-redhat7-for-56
sidebar_position: 5.131
sidebar_position: 5.132
---
# Compile StoneDB for MySQL5.6 on RHEL 7
......
---
id: compile-using-redhat7-for-57
sidebar_position: 5.132
sidebar_position: 5.131
---
# Compile StoneDB for MySQL5.7 on RHEL 7
......
{
"position": 5.14,
"label": "Compile StoneDB on Ubuntu20.04",
"collapsible": true
}
\ No newline at end of file
---
id: compile-using-ubuntu20.04-for-56
sidebar_position: 5.141
sidebar_position: 5.142
---
# Compile StoneDB for MySQL5.6 on Ubuntu 20.04
......@@ -100,7 +100,7 @@ autoreconf -i
sudo make && make install
```
The installation directory of marisa in the example is** /usr/local/stonedb-marisa**. You can change it based on your actual conditions. In this step, the following directories and files are generated in **/usr/local/stonedb-marisa/lib**.
![](./5.6-marisa.png)
![](../5.6-marisa.png)
1. Install RocksDB.
```shell
......@@ -129,7 +129,7 @@ sudo make install -j`nproc`
```
The installation directory of RocksDB in the example is **/usr/local/stonedb-gcc-rocksdb**. You can change it based on your actual conditions. In this step, the following directories and files are generated in **/usr/local/stonedb-gcc-rocksdb**.
![](./5.6-rocksdb.png)
![](../5.6-rocksdb.png)
1. Install Boost.
```shell
......@@ -141,7 +141,7 @@ cd boost_1_66_0
```
The installation directory of Boost in the example is **/usr/local/stonedb-boost**. You can change it based on your actual conditions. In this step, the following directories and files are generated in **/usr/local/stonedb-boost/lib**.
![image.png](./5.6-boost.png)
![image.png](../5.6-boost.png)
:::info
During the compilation, the occurrences of keywords **warning** and** failed** are normal, unless **error** is displayed and the CLI is automatically closed.<br />It takes about 25 minutes to install Boost.
......
---
id: compile-using-ubuntu20.04-for-57
sidebar_position: 5.142
sidebar_position: 5.141
---
# Compile StoneDB for MySQL5.7 on Ubuntu 20.04
......@@ -103,7 +103,7 @@ sudo make && make install
```
The installation directory of marisa in the example is** /usr/local/stonedb-marisa**. You can change it based on your actual conditions. In this step, the following directories and files are generated in **/usr/local/stonedb-marisa/lib**.
![](./5.7-marisa.png)
![](../5.7-marisa.png)
1. Install RocksDB.
```shell
......@@ -132,7 +132,7 @@ sudo make install -j`nproc`
```
The installation directory of RocksDB in the example is **/usr/local/stonedb-gcc-rocksdb**. You can change it based on your actual conditions. In this step, the following directories and files are generated in **/usr/local/stonedb-gcc-rocksdb**
![](./5.7-rocksdb.png)
![](../5.7-rocksdb.png)
1. Install Boost.
```shell
......@@ -144,7 +144,7 @@ cd boost_1_66_0
```
The installation directory of Boost in the example is **/usr/local/stonedb-boost**. You can change it based on your actual conditions. In this step, the following directories and files are generated in **/usr/local/stonedb-boost/lib**.
![image.png](./5.7-boost.png)
![image.png](../5.7-boost.png)
:::info
During the compilation, the occurrences of keywords **warning** and** failed** are normal, unless **error** is displayed and the CLI is automatically closed.<br />It takes about 25 minutes to install Boost.
......
......@@ -24,7 +24,7 @@ build information as follow:
```
## **Test scheme**
### **1. Set up the test environment**
For information about how to set up the test environment, see [Quick Deployment](..../../../../../02-getting-started/quick-deployment.md).
For information about how to set up the test environment, see [Quick Deployment](..../../../../../02-getting-started/quick-deployment).
### 2. Compile and deploy TPC-H
1. Download the [TPC-H](https://www.tpc.org/tpc_documents_current_versions/current_specifications5.asp) installation package, upload the package to the test machine.
......
---
id: quick-deployment
sidebar_position: 3.1
id: quick-deployment-56
sidebar_position: 3.11
---
# 快速部署
# 快速部署 StoneDB-5.6
为方便用户快速上手,安装包是已经编译好的,只需要检查自己的环境是否缺少依赖。
## 下载安装包
点击 [此处](https://static.stoneatom.com/stonedb-ce-5.6-v1.0.0.el7.x86_64.tar.gz)下载最新的安装包。
......@@ -21,17 +21,18 @@ ldd mysql
```
如果检查返回有关键字"not found",说明缺少文件,需要安装对应的依赖包。
例如:
例如:libsnappy.so.1 => not found
libsnappy.so.1 => not found
在 Ubuntu 上使用命令 "sudo apt search libsnappy" 检查,说明需要安装 libsnappy-dev。
Ubuntu 上使用命令 "sudo apt search libsnappy" 检查,说明需要安装 libsnappy-dev。在 RedHat 或者 CentOS 上使用命令 "yum search all snappy" 检查,说明需要安装 snappy-devel、snappy。
在 RedHat 或者 CentOS 上使用命令 "yum search all snappy" 检查,说明需要安装 snappy-devel、snappy。
Ubuntu 需要安装的依赖包详见 [Ubuntu 20.04 下编译 StoneDB](../04-developer-guide/00-compiling-methods/compile-using-ubuntu2004.md)
- Ubuntu 需要安装的依赖包详见 [Ubuntu 20.04 下编译 StoneDB](../../04-developer-guide/00-compiling-methods/compile-using-ubuntu2004/compile-using-ubuntu2004-for-56.md)
CentOS 需要安装的依赖包详见 [CentOS 7 下编译 StoneDB](../04-developer-guide/00-compiling-methods/compile-using-centos7.md)
- CentOS 需要安装的依赖包详见 [CentOS 7 下编译 StoneDB](../../04-developer-guide/00-compiling-methods/compile-using-centos7/compile-using-centos7-for-56.md)
- RedHat 需要安装的依赖包详见 [RedHat 7 下编译 StoneDB](../../04-developer-guide/00-compiling-methods/compile-using-redhat7/compile-using-redhat7-for-56.md)
RedHat 需要安装的依赖包详见 [RedHat 7 下编译 StoneDB](../04-developer-guide/00-compiling-methods/compile-using-redhat7.md)
## 启动实例
用户可按照手动安装和自动安装两种方式启动 StoneDB。
### 1. 创建用户
......
---
id: quick-deployment-57
sidebar_position: 3.12
---
# 快速部署 StoneDB-5.7
为方便用户快速上手,安装包是已经编译好的,只需要检查自己的环境是否缺少依赖。
## 下载安装包
点击 [此处](https://static.stoneatom.com/custom/stonedb-ce-5.7-v1.0.0.el7.x86_64.tar.gz)下载最新的安装包。
## 上传tar包并解压
```shell
cd /
tar -zxvf stonedb-ce-5.7-v1.0.0.el7.x86_64.tar.gz
```
用户可根据安装规范将安装包上传至服务器,解压出来的目录是 stonedb57,示例中的安装路径是 /stonedb57。
# 检查依赖文件
```shell
cd /stonedb57/install/bin
ldd mysqld
ldd mysql
```
如果检查返回有关键字"not found",说明缺少文件,需要安装对应的依赖包。
例如:
libsnappy.so.1 => not found
这个就说明需要在 Ubuntu 上使用命令 "sudo apt search libsnappy" 检查,说明需要安装 libsnappy-dev。
在 RedHat 或者 CentOS 上使用命令 "yum search all snappy" 检查,说明需要安装 snappy-devel、snappy。
- Ubuntu 需要安装的依赖包详见 [Ubuntu 20.04 下编译 StoneDB](../../04-developer-guide/00-compiling-methods/compile-using-ubuntu2004/compile-using-ubuntu2004-for-57.md)
- CentOS 需要安装的依赖包详见 [CentOS 7 下编译 StoneDB](../../04-developer-guide/00-compiling-methods/compile-using-centos7/compile-using-centos7-for-57.md)
- RedHat 需要安装的依赖包详见 [RedHat 7 下编译 StoneDB](../../04-developer-guide/00-compiling-methods/compile-using-redhat7/compile-using-redhat7-for-57.md)
## 启动实例
用户可按照手动安装和自动安装两种方式启动 StoneDB。
### 1. 创建用户
```shell
groupadd mysql
useradd -g mysql mysql
passwd mysql
```
### 2. 手动安装
手动创建目录、配置参数文件、初始化和启动实例。
```shell
###创建目录
mkdir -p /stonedb57/install/data
mkdir -p /stonedb57/install/binlog
mkdir -p /stonedb57/install/log
mkdir -p /stonedb57/install/tmp
mkdir -p /stonedb57/install/redolog
mkdir -p /stonedb57/install/undolog
chown -R mysql:mysql /stonedb57
###配置my.cnf
mv my.cnf my.cnf.bak
vim /stonedb57/install/my.cnf
[mysqld]
port = 3306
socket = /stonedb57/install/tmp/mysql.sock
basedir = /stonedb57/install
datadir = /stonedb57/install/data
pid_file = /stonedb57/install/data/mysqld.pid
log_error = /stonedb57/install/log/mysqld.log
innodb_log_group_home_dir = /stonedb57/install/redolog/
innodb_undo_directory = /stonedb57/install/undolog/
chown -R mysql:mysql /stonedb57/install/my.cnf
###初始化实例
/stonedb57/install/bin/mysqld --defaults-file=/stonedb57/install/my.cnf --initialize --user=mysql
###启动实例
/stonedb57/install/bin/mysqld_safe --defaults-file=/stonedb57/install/my.cnf --user=mysql &
```
### 3. 自动安装
执行 reinstall.sh 就是创建目录、初始化实例和启动实例的过程。
```shell
cd /stonedb57/install
./reinstall.sh
```
:::info
reinstall.sh 与 install.sh 的区别:
- reinstall.sh 是自动化安装脚本,执行脚本的过程是创建目录、初始化实例和启动实例的过程,只在第一次使用,其他任何时候使用都会删除整个目录,重新初始化数据库。
- install.sh 是手动安装提供的示例脚本,用户可根据自定义的安装目录修改路径,然后执行脚本,执行脚本的过程也是创建目录、初始化实例和启动实例。以上两个脚本都只能在第一次使用。
:::
### 4. 执行登录
```shell
cat /stonedb57/install/log/mysqld.log |grep passwd
[Note] A temporary password is generated for root@localhost: ceMuEuj6l4+!
/stonedb57/install/bin/mysql -uroot -p -S /stonedb57/install/tmp/mysql.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36-StoneDB-debug-log build-
Copyright (c) 2021, 2022 StoneAtom Group Holding Limited
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> alter user 'root'@'localhost' identified by 'stonedb123';
```
## 关闭实例
```shell
/stonedb57/install/bin/mysqladmin -uroot -p -S /stonedb57/install/tmp/mysql.sock shutdown
```
......@@ -6,12 +6,14 @@ sidebar_position: 5.11
# 编译方法综述
将分别介绍以下几种常用的编译方法:
[CentOS 7 下编译StoneDB](https://stoneatom.yuque.com/staff-ft8n1u/dghuxr/ry151q?view=doc_embed)
[RedHat 7 下编译StoneDB](https://stoneatom.yuque.com/staff-ft8n1u/dghuxr/xtwgr8?view=doc_embed)
[Ubuntu 20.04 下编译StoneDB](https://stoneatom.yuque.com/staff-ft8n1u/dghuxr/tamowv?view=doc_embed)
第三方依赖库集成Docker 编译镜像使用:
[Docker 编译环境搭建和使用](https://stoneatom.yuque.com/staff-ft8n1u/dghuxr/ro7qqw?view=doc_embed)
## 常用操作系统编译方法:
- [CentOS 7 下编译StoneDB](./compile-using-centos7/compile-using-centos7-for-57.md)
- [RedHat 7 下编译StoneDB](./compile-using-redhat7/compile-using-redhat7-for-57.md)
- [Ubuntu 20.04 下编译StoneDB](./compile-using-ubuntu2004/compile-using-ubuntu2004-for-57.md)
## 第三方依赖库集成 Docker 编译镜像使用:
- [Docker 编译环境搭建和使用](./compile-using-docker.md)
......
......@@ -3,7 +3,7 @@ id: compile-using-docker
sidebar_position: 5.15
---
# Docker 编译环境搭建和使用 StoneDB
# Docker 下编译使用 StoneDB
## 环境简介
由于编译环境搭建第三方库较为繁琐,且Fedora,Ubuntu等环境编译存在大量依赖缺失,需要补充安装依赖,搭建麻烦,所以搭建一个Docker Centos 编译环境容器,可以通过Docker 容器快速编译StoneDB,解决编译环境搭建繁琐问题,也可以通过Docker 容器编译后直接启动StoneDB进行调试使用。
......
---
id: compile-using-ubuntu20.04-for-56
sidebar_position: 5.141
sidebar_position: 5.142
---
# Ubuntu 20.04 下编译 StoneDB for MySQL5.6
......@@ -96,7 +96,7 @@ sudo make && make install
```
marisa 的安装路径可以根据实际情况指定,示例中的安装路径是 /usr/local/stonedb-marisa。此步骤会在 /usr/local/stonedb-marisa/lib 下生成如下目录和文件。
![](./5.6-marisa.png)
![](../5.6-marisa.png)
### 4. 安装 rocksdb
```shell
......@@ -125,7 +125,7 @@ sudo make install -j`nproc`
```
rocksdb 的安装路径可以根据实际情况指定,示例中的安装路径是 /usr/local/stonedb-gcc-rocksdb。此步骤会在 /usr/local/stonedb-gcc-rocksdb 下生成如下目录和文件。
![](./5.6-rocksdb.png)
![](../5.6-rocksdb.png)
### 5. 安装 boost
```shell
......@@ -137,7 +137,7 @@ cd boost_1_66_0
```
boost 的安装路径可以根据实际情况指定,示例中的安装路径是 /usr/local/stonedb-boost。此步骤会在 /usr/local/stonedb-boost/lib 下生成如下目录和文件。
![image.png](./5.6-boost.png)
![image.png](../5.6-boost.png)
:::info
在编译过程中,除非有关键字 "error" 报错自动退出,否则出现关键字 "warning"、"failed"是正常的,安装 boost 大概需要25分钟左右。
......
---
id: compile-using-ubuntu20.04-for-56
sidebar_position: 5.142
id: compile-using-ubuntu20.04-for-57
sidebar_position: 5.141
---
# Ubuntu 20.04 下编译 StoneDB for MySQL5.7
......@@ -94,7 +94,7 @@ sudo make && make install
```
marisa 的安装路径可以根据实际情况指定,示例中的安装路径是 /usr/local/stonedb-marisa。此步骤会在 /usr/local/stonedb-marisa/lib 下生成如下目录和文件。
![](./5.7-marisa.png)
![](../5.7-marisa.png)
### 4. 安装 rocksdb
```shell
......@@ -123,7 +123,7 @@ sudo make install -j`nproc`
```
rocksdb 的安装路径可以根据实际情况指定,示例中的安装路径是 /usr/local/stonedb-gcc-rocksdb。此步骤会在 /usr/local/stonedb-gcc-rocksdb 下生成如下目录和文件。
![](./5.7-rocksdb.png)
![](../5.7-rocksdb.png)
### 5. 安装 boost
```shell
......@@ -135,7 +135,7 @@ cd boost_1_66_0
```
boost 的安装路径可以根据实际情况指定,示例中的安装路径是 /usr/local/stonedb-boost。此步骤会在 /usr/local/stonedb-boost/lib 下生成如下目录和文件。
![image.png](./5.7-boost.png)
![image.png](../5.7-boost.png)
:::info
在编译过程中,除非有关键字 "error" 报错自动退出,否则出现关键字 "warning"、"failed"是正常的,安装 boost 大概需要25分钟左右。
......
......@@ -11,9 +11,9 @@ total used free shared buff/cache available
Mem: 251 44 1 0 205 205
Swap: 7 0 7
```
total:物理内存总大小,total = used + free + buff/cache
used:已使用的内存大小
free:空闲的内存大小
shared:共享内存大小
buff/cache:缓存内存大小
available:可用物理内存大小,available = free + buff/cache
- total:物理内存总大小,total = used + free + buff/cache
- used:已使用的内存大小
- free:空闲的内存大小
- shared:共享内存大小
- buff/cache:缓存内存大小
- available:可用物理内存大小,available = free + buff/cache
......@@ -22,47 +22,81 @@ PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
928343 root 20 0 9936 4576 3240 R 0.3 0.0 0:00.04 top
......
```
第一行
## 第一行
10:12:21:当前系统时间
up 5 days:自上一次系统启动后到现在的运行天数
4 users:登录到系统的用户数
load average:过去1分钟、5分钟、15分钟,系统负载的平均值
第二行
## 第二行
total:系统进程总数
running:处于运行状态的进程数
sleeping:处于休眠状态的进程数
stopped:处于被停止状态的进程数
zombie:处于僵尸状态进程数
第三行
## 第三行
us:用户进程占用CPU的百分比
sy:系统进程占用CPU的百分比
ni:优先级被改变过的进程占用CPU的百分比
id:空闲CPU占用的百分比
wa:IO等待占用CPU的百分比
hi:硬件中断占用CPU的百分比
si:软件中断占用CPU的百分比
st:虚拟化环境占用CPU的百分比
需要重点关注CPU的使用率,当us值较高时,说明用户进程消耗CPU时间较多,如果长时间超过50%时,应尽快优化应用服务。当sy值较高时,说明系统进程消耗CPU时间较多,比如可能是操作系统配置不合理或者出现操作系统的Bug。当wa值较高时,说明系统IO等待比较严重,比如可能是发生了大量的随机IO访问,IO带宽出现瓶颈。
第四行
## 第四行
total:物理内存总大小,单位为M
free:空闲的内存大小
used:已使用的内存大小
buff/cache:已缓存的内存大小
第五行
## 第五行
total:Swap大小
free:空闲的Swap大小
used:已使用的Swap大小
avail Mem:已缓存的Swap大小
进程列表
## 进程列表
PID:进程的id
USER:进程的拥有者
PR:进程的优先级,值越小越优先执行
NI:进程nice值,正值表示降低进程优先级,负值表示提高进程优先级,nice取值范围为(-20,19),默认情况下,进程的nice值为0
VIRT:进程占用的虚拟内存大小
RES:进程占用的物理内存大小
SHR:进程占用的共享内存大小
S:进程状态,其中S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值为负数
%CPU:进程CPU使用率
%MEM:进程内存使用率
TIME+:进程启动后占用CPU的总时间,即占用CPU使用时间的累加值
COMMAND:进程启动命令名称
......@@ -3,12 +3,13 @@ id: overview
sidebar_position: 7.1
---
# 概述
# 性能优化概述
**为什么要做优化?**
## 为什么要做优化?
当业务并发量越来越高,数据量越来越大时,系统也会变的越来越慢。如果不主动对系统做优化,严重的可能导致系统宕机,系统无法提供对外服务,这给企业带来的损失是无法预估的。
**在哪些方面做优化?**
## 在哪些方面做优化?
一般是在系统架构、应用架构、硬件配置、操作系统、数据库方面做优化。其中系统架构、应用架构、硬件配置的优化工作应该在系统上线前完成,后期随着业务的扩展也会做相应的优化。
**如何做优化?**
## 如何做优化?
操作系统优化通常是让系统资源,如CPU、内存、IO和网络得到充分的利用,避免系统资源出现瓶颈和冲突,提高整个系统查询响应时间的吞吐量。
数据库优化通常是数据库参数优化和SQL优化,其中SQL优化占据了90%以上的工作。要求深刻理解SQL的执行过程和读懂分析SQL的执行计划,最终定位到根因并给出解决方案。
......@@ -5,66 +5,65 @@ sidebar_position: 9.8
# 慢SQL诊断
慢查询日志用来记录SQL的执行时间超过long_query_time的阀值,慢查询日志支持将日志写入文件,也支持将日志写入数据库的表。慢查询日志能帮助我们捕捉到有性能问题的SQL,相关慢查询日志参数如下
慢查询日志用来记录SQL的执行时间超过long_query_time的阀值,慢查询日志支持将日志写入文件,也支持将日志写入数据库的表。慢查询日志能帮助我们捕捉到有性能问题的SQL,**相关慢查询日志参数如下**
slow_query_log:慢查询日志是否开启
- slow_query_log:慢查询日志是否开启
- slow_query_log_file:慢查询日志记录的文件
- long_query_time:SQL实际执行时间超过该参数阀值就会被记录
- log_queries_not_using_indexes:未使用索引就会被记录
- log_slow_admin_statements:是否记录管理语句,如alter、create、drop
slow_query_log_file:慢查询日志记录的文件
:::info
long_query_time 记录的是 SQL 实际执行时间,不包含锁等待时间,虽然有的 SQL 执行时间很长,但可能是由于锁等待引起的,实际上这种SQL不会被记录到慢查询日志。
:::
long_query_time:SQL实际执行时间超过该参数阀值就会被记录
**慢查询日志输出解释**
log_queries_not_using_indexes:未使用索引就会被记录
log_slow_admin_statements:是否记录管理语句,如alter、create、drop
注:long_query_time记录的是SQL实际执行时间,不包含锁等待时间,虽然有的SQL执行时间很长,但可能是由于锁等待引起的,实际上这种SQL不会被记录到慢查询日志。
慢查询日志输出解释:
Query_time:SQL总执行时间,即实际执行时间 + 锁等待时间
Lock_time:锁等待时间
Rows_sent:发送给客户端的行数
Rows_examined:表示执行过程中扫描了多少行,这个值是在执行器每次调用存储引擎获取数据行的时候累加的,是在Server层统计的
注:在有些场景下,执行器调用一次,在存储引擎内部则扫描了多行,因此存储引擎扫描行数和rows_examined并不是完全相同的。
- Query_time:SQL总执行时间,即实际执行时间 + 锁等待时间
- Lock_time:锁等待时间
- Rows_sent:发送给客户端的行数
- Rows_examined:表示执行过程中扫描了多少行,这个值是在执行器每次调用存储引擎获取数据行的时候累加的,是在Server层统计的
:::info
在有些场景下,执行器调用一次,在存储引擎内部则扫描了多行,因此存储引擎扫描行数和rows_examined并不是完全相同的。
:::
## mysqldumpslow
mysqldumpslow常用于对慢查询日志进行汇总分类。
1)查看慢查询日志中TOP 10(以平均执行时间降序排列)
1. 查看慢查询日志中TOP 10(以平均执行时间降序排列)
```shell
mysqldumpslow -t 10 /var/lib/mysql/mysql-slow.log | more
```
2查看慢查询日志中返回总记录数最多的TOP 10(以返回总记录数降序排列)
2. 查看慢查询日志中返回总记录数最多的TOP 10(以返回总记录数降序排列)
```shell
mysqldumpslow -s r -t 10 /var/lib/mysql/mysql-slow.log | more
```
3查看慢查询日志中总执行次数最多的TOP 10(以总执行次数降序排列)
3. 查看慢查询日志中总执行次数最多的TOP 10(以总执行次数降序排列)
```shell
mysqldumpslow -s c -t 10 /var/lib/mysql/mysql-slow.log | more
```
4查看慢查询日志中按照总执行时间排序,前10条包含left join的SQL
4. 查看慢查询日志中按照总执行时间排序,前10条包含left join的SQL
```shell
mysqldumpslow -s t -t 10 -g "left join" /var/lib/mysql/mysql-slow.log | more
```
相关参数解释:
-s:降序排序
al:平均锁定时间排序
ar:平均返回记录数排序
at:平均执行时间排序,默认
c:总执行次数排序
l:总锁定时间排序
r:总返回记录数排序
t:总执行时间排序
-t NUM:返回top n
-g:使用正则表达式
-h:根据主机名选择
-i:根据实例名选择
-l:不要从总时间减去锁定时间
- s:降序排序
- al:平均锁定时间排序
- ar:平均返回记录数排序
- at:平均执行时间排序,默认
- c:总执行次数排序
- l:总锁定时间排序
- r:总返回记录数排序
- t:总执行时间排序
- t NUM:返回top n
- g:使用正则表达式
- h:根据主机名选择
- i:根据实例名选择
- l:不要从总时间减去锁定时间
## profiling
profiling分析工具可以获得一条SQL在整个执行过程中的每一步状态,以及每一步状态的资源消耗情况,如CPU、IO、Swap,同时还能获得每一步状态的函数调用,以及该函数所在的源文件和出现的位置。
用法示例如下:
开启当前线程的profiling:
```sql
set profiling=on;
......@@ -104,25 +103,26 @@ show profile all for query query_id;
+----------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+---------------+-------------------+-------------------+-------------------+-------+-----------------------+----------------------+-------------+
```
一个SQL需要经历如下的Status过程:
starting:语法语义解析,生成解析树
checking permissions:根据解析后的解析树,对需要访问的表进行鉴权
opening tables:打开访问的表
System lock:确认是由哪种锁引起的
optimizing/statistics/preparing:这3个状态处于语句的物理和逻辑优化阶段,之后生成执行计划
Sending data:服务层与存储引擎层正在进行数据交互
Update:insert语句,如果遇到行锁会处于这个状态下
Updating:delete/update语句,如果遇到行锁会处于这个状态下
query end:提交过程,如果遇到大事务会处于这个状态下
closing tables:关闭表的访问,与opening tables对应
freeing items:释放解析树
如果Status长时间处于如下几种状态,说明SQL存在性能问题或者等待。
Sending data:服务层与存储引擎层正在进行数据交互
converting HEAP to MyISAM:查询结果集太大,内存临时表不够用,需要暂存到磁盘临时文件
Creating tmp table:创建临时表,然后拷贝数据到临时表,用完之后删除临时表,通常是有group by、distinct、子查询操作
Copying to tmp table on disk:把内存中的临时表拷贝到磁盘
Creating sort index:在做排序操作,通常是order by
locked:被阻塞
Waiting for table metadata lock:发生元数据锁等待
1. starting:语法语义解析,生成解析树
2. checking permissions:根据解析后的解析树,对需要访问的表进行鉴权
3. opening tables:打开访问的表
4. System lock:确认是由哪种锁引起的
5. optimizing/statistics/preparing:这3个状态处于语句的物理和逻辑优化阶段,之后生成执行计划
6. Sending data:服务层与存储引擎层正在进行数据交互
7. Update:insert语句,如果遇到行锁会处于这个状态下
8. Updating:delete/update语句,如果遇到行锁会处于这个状态下
9. query end:提交过程,如果遇到大事务会处于这个状态下
10. closing tables:关闭表的访问,与opening tables对应
11. freeing items:释放解析树
12. 如果Status长时间处于如下几种状态,说明SQL存在性能问题或者等待。
13. Sending data:服务层与存储引擎层正在进行数据交互
14. converting HEAP to MyISAM:查询结果集太大,内存临时表不够用,需要暂存到磁盘临时文件
15. Creating tmp table:创建临时表,然后拷贝数据到临时表,用完之后删除临时表,通常是有group by、distinct、子查询操作
16. Copying to tmp table on disk:把内存中的临时表拷贝到磁盘
17. Creating sort index:在做排序操作,通常是order by
18. locked:被阻塞
19. Waiting for table metadata lock:发生元数据锁等待
## optimizer trace
有时候我们不仅想知道SQL的执行计划,还想知道优化器为什么选择这个执行计划。optimizer trace功能可以让我们知道优化器生成执行计划的过程,这个功能是由系统变量optimizer_trace来决定的。
```sql
......@@ -135,58 +135,67 @@ mysql> show variables like 'optimizer_trace';
```
enabled=off表示optimizer trace默认是关闭的,如果要开启,需要设置enabled=on,而且一般只作为当前线程开启;one_line=off表示输出格式,默认off表示换行输出。
使用optimizer trace功能的完整步骤如下:
1)设置optimizer_trace缓存大小,目的是保存完整的trace,不要被截断
1. 设置optimizer_trace缓存大小,目的是保存完整的trace,不要被截断
```sql
set optimizer_trace_max_mem_size = 100*1024;
```
2开启optimizer_trace
2. 开启optimizer_trace
```sql
set optimizer_trace='enabled=on';
```
3)执行具体的SQL
注:如果SQL执行时间很长,而又不想等SQL执行结束才生成trace,使用explain SQL也是可以生成trace的。
4)从optimizer_trace表中查看上一个SQL的优化过程
3. 执行具体的SQL
:::tip
如果SQL执行时间很长,而又不想等SQL执行结束才生成trace,使用explain SQL也是可以生成trace的。
:::
4. 从optimizer_trace表中查看上一个SQL的优化过程
```sql
select * from information_schema.optimizer_trace;
```
5关闭optimizer_trace
5. 关闭optimizer_trace
```sql
set optimizer_trace='enabled=off';
```
optimizer trace的输出分3个阶段,分别是:
1)join_preparation
2)join_optimization
3)join_execution
1. join_preparation
2. join_optimization
3. join_execution
其中join_optimization阶段是基于成本计算的。对于单表查询来说,主要关注的是row_estimation过程,这个过程分析了全表扫描成本和各个索引扫描的成本。对于多表关联查询来说,主要关注的是considered_execution_plans过程,这个过程分析了不同表关联顺序的成本。
join_optimization阶段需要关注的部分
condition_processing:优化器在这个过程会做查询条件处理,如等值传递转换、常量传递转换、消除没用的条件。例如:原始的查询条件是:"a=1 and b=a",经过转换后是:"a=1 and b=1"
rows_estimation:单表查询的行预估
table_scan:全表扫描统计
rows:全表扫描预估行数
cost:全表扫描的成本
potential_range_indexes:可能使用的索引
"index": "PRIMARY", --->表示主键索引不可用
"usable": false,
"cause": "not_applicable"
"index": "idx_xxx", --->表示idx_xxx索引可能被使用
"usable": true,
"key_parts": [
"column1",
"column2",
"id"
analyzing_range_alternatives:分析各种可能使用的索引的成本
"index": "idx_xxx",
"ranges": [
"2 <= column1 <= 2 AND 0 <= column2 <= 0"
],
"index_dives_for_eq_ranges": true, --->使用index dive
"rowid_ordered": true, --->使用该索引获取的记录是否按照主键排序
"using_mrr": false, --->是否使用mrr
"index_only": false, --->是否使用索引覆盖
"rows": xxx, --->使用该索引预估行数
"cost": xxx, --->使用该索引的成本
"chosen": true --->是否选择该索引
chosen_range_access_summary:最终选择的执行计划
considered_execution_plans:分析各种可能的执行计划,常用于多表关联查询
attaching_conditions_to_tables:尝试给查询添加一些其他的查询条件
reconsidering_access_paths_for_index_ordering:是否因排序导致执行计划改变
### join_optimization 阶段需要关注的部分:
- condition_processing:优化器在这个过程会做查询条件处理,如等值传递转换、常量传递转换、消除没用的条件。例如:原始的查询条件是:"a=1 and b=a",经过转换后是:"a=1 and b=1"
- rows_estimation:单表查询的行预估
- table_scan:全表扫描统计
- rows:全表扫描预估行数
- cost:全表扫描的成本
- potential_range_indexes:可能使用的索引
- "index": "PRIMARY", --->表示主键索引不可用
- "usable": false,
- "cause": "not_applicable"
- "index": "idx_xxx", --->表示idx_xxx索引可能被使用
- "usable": true,
- "key_parts": [
"column1",
"column2",
"id"]
- analyzing_range_alternatives:分析各种可能使用的索引的成本
- "index": "idx_xxx",
- "ranges": [
"2 <= column1 <= 2 AND 0 <= column2 <= 0"
],
- "index_dives_for_eq_ranges": true, --->使用index dive
- "rowid_ordered": true, --->使用该索引获取的记录是否按照主键排序
- "using_mrr": false, --->是否使用mrr
- "index_only": false, --->是否使用索引覆盖
- "rows": xxx, --->使用该索引预估行数
- "cost": xxx, --->使用该索引的成本
- "chosen": true --->是否选择该索引
- chosen_range_access_summary:最终选择的执行计划
- considered_execution_plans:分析各种可能的执行计划,常用于多表关联查询
- attaching_conditions_to_tables:尝试给查询添加一些其他的查询条件
- reconsidering_access_paths_for_index_ordering:是否因排序导致执行计划改变
......@@ -5,16 +5,16 @@ sidebar_position: 10.2
# 产品FAQ
**StoneDB与MySQL的兼容性如何?**
StoneDB高度兼容MySQL 5.6、5.7协议和MySQL生态等重要特性,支持MySQL常用的功能及语法。
由于StoneDB本身的一些特性,部分操作和功能尚未得到支持,如不支持创建索引、不支持删除数据等。
**StoneDB有自己的优化器吗?**
StoneDB是在原生的MySQL加入的存储引擎,StoneDB有自己的优化器,但StoneDB实际也会利用原生的MySQL的优化器做一些查询解析和重写机制。
**StoneDB为什么没有唯一约束?**
列式存储具有数据压缩特性,数据压缩比率是由压缩算法、列的数据类型、数据重复度等决定的。如果列有唯一约束,那么列中每行的数据都是唯一的,数据压缩比率就低。在InnoDB和StoneDB下,分别向具有唯一值的列插入6000万条数据,InnoDB表大小16G多,StoneDB表大小5G多,压缩比率为3:1多,而一般情况下是可以达到10:1以上的。
**StoneDB需要创建索引吗?**
如果数据库使用的是B-Tree或者B+Tree的数据结构,在查询少量结果集的情况下,通过索引是能高效定位到数据行的。但StoneDB利用的是知识网格技术,只需要对数据包解压缩,是不需要创建索引的。
**StoneDB支持事务吗?**
事务分为安全性事务和非安全性事务,严格遵守ACID属性的属于安全性事务。由于StoneDB没有redo和undo,属于非安全性事务,所以是不支持事务的。
**StoneDB的表和其他存储引擎的表能关联查询吗?**
默认情况是不允许跨存储引擎的表关联查询的,可以修改参数stonedb_ini_allowmysqlquerypath=1,这样是支持跨存储引擎的表关联查询的。
## StoneDB与MySQL的兼容性如何?
StoneDB 高度兼容 MySQL 5.6、5.7 协议和 MySQL 生态等重要特性,支持 MySQL 常用的功能及语法。
由于 StoneDB 本身的一些特性,部分操作和功能尚未得到支持,如不支持创建索引、不支持删除数据等。
## StoneDB有自己的优化器吗?
StoneDB 是在原生的 MySQL 加入的存储引擎,StoneDB 有自己的优化器,但 StoneDB 实际也会利用原生的 MySQL 的优化器做一些查询解析和重写机制。
## StoneDB为什么没有唯一约束?
列式存储具有数据压缩特性,数据压缩比率是由压缩算法、列的数据类型、数据重复度等决定的。如果列有唯一约束,那么列中每行的数据都是唯一的,数据压缩比率就低。在 InnoDB 和 StoneDB 下,分别向具有唯一值的列插入 6000 万条数据,InnoDB 表大小 16G 多,StoneDB 表大小 5G 多,压缩比率为3:1多,而一般情况下是可以达到 10:1 以上的。
## StoneDB需要创建索引吗?
如果数据库使用的是 B-Tree 或者 B+Tree 的数据结构,在查询少量结果集的情况下,通过索引是能高效定位到数据行的。但 StoneDB 利用的是知识网格技术,只需要对数据包解压缩,是不需要创建索引的。
## StoneDB支持事务吗?
事务分为安全性事务和非安全性事务,严格遵守 ACID 属性的属于安全性事务。由于 StoneDB 没有 redo 和 undo,属于非安全性事务,所以是不支持事务的。
## StoneDB的表和其他存储引擎的表能关联查询吗?
默认情况是不允许跨存储引擎的表关联查询的,可以修改参数 stonedb_ini_allowmysqlquerypath=1,这样是支持跨存储引擎的表关联查询的。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册