暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

第112期,IvorySQL 与 Highgo 的兼容模式

原创 ByteHouse 2026-01-08
690

摘要:从使用中感受兼容模式带来的麻烦,并不是所有的数据都需要去做兼容模式。

Highgo数据库注册为服务

[root@localhost hgupload]# cd /opt/highgo/hgdb-v9.0/
[root@localhost hgdb-v9.0]# cd scripts/
[root@localhost scripts]# ll
总用量 24
-rwxrwxr-x 1 highgo highgo  565  1月  8 10:32 env.sh
-rwxrwxr-x 1 highgo highgo 2276  8月  8 11:43 register_db_service.sh
-rwxrwxr-x 1 highgo highgo  654  1月  8 10:32 runsql.sh
-rwxrwxr-x 1 highgo highgo  800  8月  8 11:43 service_status.sh
-rwxrwxr-x 1 highgo highgo  837  8月  8 11:43 unregister_db_service.sh
-rwxrwxr-x 1 highgo highgo  472  8月  8 11:43 unset_env.sh
[root@localhost scripts]# 
[highgo@localhost scripts]$ ll
总用量 24
-rwxrwxr-x 1 highgo highgo  565  1月  8 10:32 env.sh
-rwxrwxr-x 1 highgo highgo 2276  8月  8 11:43 register_db_service.sh
-rwxrwxr-x 1 highgo highgo  654  1月  8 10:32 runsql.sh
-rwxrwxr-x 1 highgo highgo  800  8月  8 11:43 service_status.sh
-rwxrwxr-x 1 highgo highgo  837  8月  8 11:43 unregister_db_service.sh
-rwxrwxr-x 1 highgo highgo  472  8月  8 11:43 unset_env.sh
[highgo@localhost scripts]$


[highgo@localhost scripts]$ cat register_db_service.sh 
#!/bin/bash -e

if [ "$#" -ne "4" ]; then
    echo "Usage: $0 <DB_HOME> <DB_DATA> <SERVICE_NAME> <USER>"
    exit 1
fi

DB_HOME=$1
DB_DATA=$2
SERVICE_NAME=$3
USER=$4

SYSTEMD_PATH="/lib/systemd/system"
SYSTEMD_SERVICE_FILE="$SYSTEMD_PATH/$SERVICE_NAME.service"
INITD_PATH="/etc/init.d"
INITD_SERVICE_FILE="$INITD_PATH/$SERVICE_NAME"

check_service_exist() {
    if [[ -f "$SYSTEMD_SERVICE_FILE" || -f "$INITD_SERVICE_FILE" ]]; then
        echo "Service '$SERVICE_NAME' already exists."
        exit 2
    fi
}

# Configure service for systemd
systemd_service() {
cat > "$SYSTEMD_SERVICE_FILE" << EOF
[Unit]
Description=HighGo database service
Requires=network.target local-fs.target
After=network.target local-fs.target

[Service]
User=$USER
Type=forking
ExecStart=$DB_HOME/bin/pg_ctl start -D $DB_DATA
ExecStop=$DB_HOME/bin/pg_ctl stop -D $DB_DATA
TimeoutSec=60

[Install]
WantedBy=multi-user.target graphical.target

EOF
}

# Configure service for System V init
initd_service() {
cat > "$INITD_SERVICE_FILE" << EOF
#!/bin/bash -xe
# chkconfig: 2345 99 01
# description: HighGo database service
### BEGIN INIT INFO
# Provides:          highgo
# Required-Start:    \$local_fs \$network
# Required-Stop:     \$local_fs \$network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: HGDB
# Description:       HighGo database service
### END INIT INFO
case "\$1" in
    start)
        $DB_HOME/bin/pg_ctl start -D $DB_DATA
    ;;
    stop)
        $DB_HOME/bin/pg_ctl stop -D $DB_DATA
    ;;
    restart)
        $DB_HOME/bin/pg_ctl restart -D $DB_DATA
    ;;
    status)
        $DB_HOME/bin/pg_ctl status -D $DB_DATA
    ;;
    *)
        echo "Usage: service $SERVICE_NAME {start|stop|restart|status}"
    ;;
esac
EOF
}

check_service_exist
# Register Service
if [ -d "$SYSTEMD_PATH" ]; then
    if [ "$(getenforce 2>/dev/null ||:)" = "Enforcing" ]; then
        chcon -R -t bin_t "$DB_HOME/bin"
    fi
    systemd_service
    systemctl enable "$SERVICE_NAME.service"
    systemctl daemon-reload
    systemctl start "$SERVICE_NAME.service"
elif [ -d "$INITD_PATH" ]; then
    initd_service
    chmod +x "$INITD_SERVICE_FILE"
    chkconfig "$SERVICE_NAME" on
    service "$SERVICE_NAME" start
fi
echo "Successfully registered '$SERVICE_NAME' service."
[highgo@localhost scripts]$ ll

--- 注销服务
[highgo@localhost scripts]$ cat unregister_db_service.sh 
#!/bin/bash -e

if [ "$#" -ne "1" ]; then
    echo "Usage: $0 <SERVICE_NAME>"
    exit 1
fi

SERVICE_NAME=$1
SYSTEMD_SERVICE_FILE="/lib/systemd/system/$SERVICE_NAME.service"
INITD_SERVICE_FILE="/etc/init.d/$SERVICE_NAME"

if [ -f "$SYSTEMD_SERVICE_FILE" ]; then
    systemctl stop "$SERVICE_NAME.service"
    systemctl disable "$SERVICE_NAME.service"
    rm -f "/etc/systemd/system/multi-user.target.wants/$SERVICE_NAME.service"
    rm -f "/etc/systemd/system/graphical.target.wants/$SERVICE_NAME.service"
    rm -f "$SYSTEMD_SERVICE_FILE"
    systemctl daemon-reload
elif [ -f "$INITD_SERVICE_FILE" ]; then
    service "$SERVICE_NAME" stop
    update-rc.d -f "$SERVICE_NAME" remove
    rm -f "$INITD_SERVICE_FILE"
else
    echo "Service '$SERVICE_NAME' not found."
    exit 2
fi
echo "Successfully uninstalled '$SERVICE_NAME' service."
[highgo@localhost scripts]$ ll

--- 设置环境变量
[highgo@localhost scripts]$ cat env.sh 
#!/bin/bash

INSTALL_DIR=/opt/highgo/hgdb-v9.0

# Path manipulation
pathmunge () {
    case ":${PATH}:" in
        *:"$1":*)
            ;;
        *)
            if [ "$2" = "after" ] ; then
                export PATH=$PATH:$1
            else
                export PATH=$1:$PATH
            fi
    esac
}

if [ -d "$INSTALL_DIR/tools/migration" ]; then
    pathmunge "$INSTALL_DIR/jdk/bin"
    export HG_MIGRATION_HOME=$INSTALL_DIR/tools/migration
fi

# include database
if [ -d "$INSTALL_DIR/bin" ]; then
    pathmunge "$INSTALL_DIR/bin"
fi

unset -f pathmunge
[highgo@localhost scripts]$ ll

--- 取消环境变量
[highgo@localhost scripts]$ cat unset_env.sh 
#!/bin/bash

ENV_ID="# highgo environment"

BASHRC="$HOME/.bashrc"
BASH_PROFILE="$HOME/.bash_profile"
PROFILE="$HOME/.profile"

unset_env() {
    local CONFIG_FILE=$1
    if [ -f "$CONFIG_FILE" ]; then
        if grep -q "$ENV_ID" "$CONFIG_FILE"; then
            sed -i "/${ENV_ID}/{N;d;}" "$CONFIG_FILE"
			sed -i -e :a -e '/^\n*$/{$d;N;ba' -e '}' "$CONFIG_FILE"
        fi
    fi
}

unset_env "$BASHRC"
unset_env "$BASH_PROFILE"
unset_env "$PROFILE"
unset -f unset_env
[highgo@localhost scripts]$ ll

--- 注册数据库
[highgo@localhost scripts]$ ./register_db_service.sh 
Usage: ./register_db_service.sh <DB_HOME> <DB_DATA> <SERVICE_NAME> <USER>
[highgo@localhost scripts]$ ./register_db_service.sh /opt/highgo/hgdb-v9.0 /opt/highgo/hgdb-v9.0/data highgo highgo
./register_db_service.sh:行27: /lib/systemd/system/highgo.service: 权限不够
[highgo@localhost scripts]$ 


[root@localhost scripts]# ./register_db_service.sh /opt/highgo/hgdb-v9.0 /opt/highgo/hgdb-v9.0/data highgo highgo
Created symlink /etc/systemd/system/multi-user.target.wants/highgo.service → /usr/lib/systemd/system/highgo.service.
Created symlink /etc/systemd/system/graphical.target.wants/highgo.service → /usr/lib/systemd/system/highgo.service.
Successfully registered 'highgo' service.
[root@localhost scripts]# 
[root@localhost scripts]# 
[root@localhost scripts]# 
[root@localhost scripts]# 
[root@localhost scripts]# systemctl status highgo
● highgo.service - HighGo database service
   Loaded: loaded (/usr/lib/systemd/system/highgo.service; enabled; vendor pres>
   Active: active (running) since Thu 2026-01-08 10:39:59 CST; 14s ago
  Process: 42061 ExecStart=/opt/highgo/hgdb-v9.0/bin/pg_ctl start -D /opt/highg>
 Main PID: 42063 (postgres)
    Tasks: 8
   Memory: 31.3M
   CGroup: /system.slice/highgo.service
           ├─42063 /opt/highgo/hgdb-v9.0/bin/postgres -D /opt/highgo/hgdb-v9.0/>
           ├─42065 postgres: checkpointer
           ├─42066 postgres: background writer
           ├─42067 postgres: walwriter
           ├─42068 postgres: autovacuum launcher
           ├─42069 postgres: stats collector
           ├─42070 postgres: pg_audit launcher
           └─42071 postgres: logical replication launcher

1月 08 10:39:59 localhost.localdomain pg_ctl[42063]: 2026-01-08 10:39:59.281 CS>
1月 08 10:39:59 localhost.localdomain pg_ctl[42063]: 2026-01-08 10:39:59.281 CS>
1月 08 10:39:59 localhost.localdomain pg_ctl[42063]: 2026-01-08 10:39:59.281 CS>
1月 08 10:39:59 localhost.localdomain pg_ctl[42063]: 2026-01-08 10:39:59.283 CS>
1月 08 10:39:59 localhost.localdomain pg_ctl[42063]: 2026-01-08 10:39:59.285 CS>
1月 08 10:39:59 localhost.localdomain pg_ctl[42064]: 2026-01-08 10:39:59.336 CS>
[root@localhost scripts]# ss -lntp
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    Process                                                                         
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*        users:(("sshd",pid=5029,fd=5))                                                 
LISTEN    0         244              127.0.0.1:5866             0.0.0.0:*        users:(("postgres",pid=42063,fd=6))                                            
LISTEN    0         244              127.0.0.1:1521             0.0.0.0:*        users:(("postgres",pid=42063,fd=8))                                            
LISTEN    0         128                   [::]:22                  [::]:*        users:(("sshd",pid=5029,fd=6))                                                 
LISTEN    0         244                  [::1]:5866                [::]:*        users:(("postgres",pid=42063,fd=5))                                            
LISTEN    0         244                  [::1]:1521                [::]:*        users:(("postgres",pid=42063,fd=7))                                            
[root@localhost scripts]# 

IvorySQL 初始化及兼容模式

IvorySQL 初始化模式选择

IvorySQL 在初始化过程中支持两种数据库模式:

  • PG 模式:保持与原生 PostgreSQL 的兼容性
  • Oracle 模式(默认):提供 Oracle 语法兼容及增强功能

用户可通过 initdb 命令参数指定初始化模式,实现不同场景下的兼容性需求。

initdb 在开始阶段会解析输入的命令行参数。

参数 功能描述 可选值 默认值
-m 指定数据库模式 oracle/pg oracle
-C 设置 Oracle 兼容的大小写转换模式 interchange/normal/lowercase interchange

文件路径初始化

执行 setup_data_file_paths() 函数完成关键文件路径配置:if (DB_PG == database_mode) set_input(&bki_file, "postgres.bki");else set_input(&bki_file, "postgres_oracle.bki");

路径检查机制:

  1. 验证 BKI 文件的存在性(postgres_oracle.bki postgres.bki)
  2. 确认配置文件模板的可用性
  3. 建立与数据库模式对应的系统目录结构

数据目录初始化流程

通过 initialize_data_directory() 函数完成核心初始化操作:

目录结构创建

调用 create_data_directory()创建主数据目录(PGDATA)。

通过 create_xlog_or_symlink() 建立 WAL 日志目录。

循环创建 base,global 等标准子目录。

配置文件初始化

调用 set_null_conf() 创建空的 postgresql.conf。

Oracle 模式下额外创建 ivorysql.conf 配置文件。

调用 setup_config() 将配置信息写入 postgresql.conf。在写入配置时,如果是 Oracle 模式,则会额外向 ivorysql.conf 中写入配置信息。

模板数据库引导

执行 bootstrap_template1() 加载对应模式的 BKI 文件初始化 template1 模板数据库,在此期间,IvorySQL 会将数据库模式(oracle/pg)和大小写转换模式写入到 pg_control 文件中。后面数据库启动时会将这些信息读取出来并设置相应的 GUC 变量。

load_plisql():安装兼容 Oracle PL/SQL 的 PL/iSQL 过程语言

load_ivorysql_ora():加载核心 Oracle 兼容层扩展

make_ivorysql():创建默认的 ivorysql 数据库

Oracle 兼容用户名处理

当数据库模式是 Oracle 时,会对用户名进行强制小写转换。

技术细节与扩展

在 PostgreSQL 中,“bki” 是 “Backend Interface” 的简写。Backend Interface 是 PostgreSQL 内部用于引导(bootstrap)数据库系统的一组工具和文件集合。

Backend Interface 主要用于初始化 PostgreSQL 数据库系统的基础结构,包括系统目录(system catalog)、系统表(system table)以及其他必要的系统对象。这些系统目录和表存储了 PostgreSQL 数据库系统的元数据信息,如数据库对象、表结构、索引信息等。

genbki.pl 处理系统表文件如 pg_class.h,pg_namespace.h,pg_proc.h 等,并生成 postgres.bki 供 initdb 加载,主要是加载初始化数据,如创建系统表,系统函数和预定义类型等。

在 initdb 前的编译阶段,会通过 genbki.pl 生成 postgres.bki 和 postgres_oracle.bki,postgres.bki 保持 PostgreSQL 原样,postgres_ora.bki
在 PostgreSQL 的基础上增加 Oracle 兼容的系统对象。

img

参考文档:https://www.modb.pro/db/1919577161774673920

highdb v9.0 数据库初始化

  1. 默认的兼容模式
[highgo@localhost data]$ initdb -D /opt/highgo/hgdb-v9.0/data
属于此数据库系统的文件宿主为用户 "highgo".
此用户也必须为服务器进程的宿主.
数据库簇将使用本地化语言 "zh_CN.UTF-8"进行初始化.
默认的数据库编码已经相应的设置为 "UTF8".
initdb: 无法为本地化语言环境"zh_CN.UTF-8"找到合适的文本搜索配置
缺省的文本搜索配置将会被设置到"simple"

禁止为数据页生成校验和.
Cluster file encryption is disabled.

修复已存在目录 /opt/highgo/hgdb-v9.0/data 的权限 ... 成功
正在创建子目录 ... 成功
选择动态共享内存实现 ......posix
选择默认最大联接数 (max_connections) ... 100
选择默认共享缓冲区大小 (shared_buffers) ... 128MB
选择默认时区 ... Asia/Shanghai
创建配置文件 ... 成功
正在运行自举脚本 ...成功
正在执行自举后初始化 ...成功
同步数据到磁盘...成功

initdb: 警告: 为本地连接启用"trust"身份验证
你可以通过编辑 pg_hba.conf 更改或你下次
执行 initdb 时使用 -A或者--auth-local和--auth-host选项.

成功。您现在可以用下面的命令开启数据库服务器:

    pg_ctl -D /opt/highgo/hgdb-v9.0/data -l 日志文件 start

[highgo@localhost data]$ 

[highgo@localhost data]$ ll
总用量 64
drwx------ 5 highgo highgo    57  1月  8 11:39 base
drwx------ 2 highgo highgo  4096  1月  8 11:39 global
-rw------- 1 highgo highgo   967  1月  8 11:39 ivorysql.oracle.conf
drwx------ 3 highgo highgo    28  1月  8 11:39 pgaudit
drwx------ 2 highgo highgo    10  1月  8 11:39 pg_commit_ts
drwx------ 2 highgo highgo    10  1月  8 11:39 pg_cryptokeys
drwx------ 2 highgo highgo    10  1月  8 11:39 pg_dynshmem
drwx------ 2 highgo highgo    10  1月  8 11:39 pg_fdwxact
-rw------- 1 highgo highgo  4789  1月  8 11:39 pg_hba.conf
-rw------- 1 highgo highgo  1636  1月  8 11:39 pg_ident.conf
drwx------ 4 highgo highgo    84  1月  8 11:39 pg_logical
drwx------ 4 highgo highgo    48  1月  8 11:39 pg_multixact
drwx------ 2 highgo highgo    10  1月  8 11:39 pg_notify
drwx------ 2 highgo highgo    10  1月  8 11:39 pg_replslot
drwx------ 2 highgo highgo    10  1月  8 11:39 pg_serial
drwx------ 2 highgo highgo    10  1月  8 11:39 pg_snapshots
drwx------ 2 highgo highgo    10  1月  8 11:39 pg_stat
drwx------ 2 highgo highgo    10  1月  8 11:39 pg_stat_tmp
drwx------ 2 highgo highgo    26  1月  8 11:39 pg_subtrans
drwx------ 2 highgo highgo    10  1月  8 11:39 pg_tblspc
drwx------ 2 highgo highgo    10  1月  8 11:39 pg_twophase
-rw------- 1 highgo highgo     3  1月  8 11:39 PG_VERSION
drwx------ 3 highgo highgo   108  1月  8 11:39 pg_wal
drwx------ 2 highgo highgo    26  1月  8 11:39 pg_xact
-rw------- 1 highgo highgo    88  1月  8 11:39 postgresql.auto.conf
-rw------- 1 highgo highgo 30592  1月  8 11:39 postgresql.conf
-rw------- 1 highgo highgo   933  1月  8 11:39 sec_pg.conf
[highgo@localhost data]$ 


[root@localhost data]# cat ivorysql.oracle.conf 
#------------------------------------------------------------------------------
#Oracle COMPATIBLE Mode GUC parameters
#------------------------------------------------------------------------------

#ivorysql.listen_addresses = 'localhost'		# what IP address(es) of Oracle mode to listen on;
												# comma-separated list of addresses;
												# defaults to 'localhost'; use '*' for all
												# (change requires restart)
#ivorysql.port = 1521							# (change requires restart)

ivorysql.enable_emptystring_to_NULL = 'on'
shared_preload_libraries = 'gb18030_2022, liboracle_parser, ivorysql_ora, pg_object, restricted_dba, pg_audit, sqlite_fdw, credcheck'		# (change requires restart)
#ivorysql.default_collation_is_c = on
#ivorysql.enable_blankspace_compare = on						# set to ignore blank space while in query
#ivorysql.enable_ora_default_collation = off
#ivorysql.subquery_with_raw_collation = on						# Replace pseudo-collation back in Set subquery[root@localhost data]# vim postgresql.conf 
[root@localhost data]# 
  1. 使用pg模式
[highgo@localhost data]$ initdb -m pg -D /opt/highgo/hgdb-v9.0/data
属于此数据库系统的文件宿主为用户 "highgo".
此用户也必须为服务器进程的宿主.
数据库簇将使用本地化语言 "zh_CN.UTF-8"进行初始化.
默认的数据库编码已经相应的设置为 "UTF8".
initdb: 无法为本地化语言环境"zh_CN.UTF-8"找到合适的文本搜索配置
缺省的文本搜索配置将会被设置到"simple"

禁止为数据页生成校验和.
Cluster file encryption is disabled.

修复已存在目录 /opt/highgo/hgdb-v9.0/data 的权限 ... 成功
正在创建子目录 ... 成功
选择动态共享内存实现 ......posix
选择默认最大联接数 (max_connections) ... 100
选择默认共享缓冲区大小 (shared_buffers) ... 128MB
选择默认时区 ... Asia/Shanghai
创建配置文件 ... 成功
正在运行自举脚本 ...成功
正在执行自举后初始化 ...成功
同步数据到磁盘...成功

initdb: 警告: 为本地连接启用"trust"身份验证
你可以通过编辑 pg_hba.conf 更改或你下次
执行 initdb 时使用 -A或者--auth-local和--auth-host选项.

成功。您现在可以用下面的命令开启数据库服务器:

    pg_ctl -D /opt/highgo/hgdb-v9.0/data -l 日志文件 start

[highgo@localhost data]$ ll
总用量 68
drwx------ 5 highgo highgo    57  1月  8 11:37 base
drwx------ 2 highgo highgo  4096  1月  8 11:37 global
drwx------ 3 highgo highgo    28  1月  8 11:37 pgaudit
drwx------ 2 highgo highgo    10  1月  8 11:37 pg_commit_ts
drwx------ 2 highgo highgo    10  1月  8 11:37 pg_cryptokeys
drwx------ 2 highgo highgo    10  1月  8 11:37 pg_dynshmem
drwx------ 2 highgo highgo    10  1月  8 11:37 pg_fdwxact
-rw------- 1 highgo highgo  4789  1月  8 11:37 pg_hba.conf
-rw------- 1 highgo highgo  1636  1月  8 11:37 pg_ident.conf
drwx------ 4 highgo highgo    84  1月  8 11:37 pg_logical
drwx------ 4 highgo highgo    48  1月  8 11:37 pg_multixact
drwx------ 2 highgo highgo    10  1月  8 11:37 pg_notify
drwx------ 2 highgo highgo    10  1月  8 11:37 pg_replslot
drwx------ 2 highgo highgo    10  1月  8 11:37 pg_serial
drwx------ 2 highgo highgo    10  1月  8 11:37 pg_snapshots
drwx------ 2 highgo highgo    10  1月  8 11:37 pg_stat
drwx------ 2 highgo highgo    33  1月  8 11:37 pg_stat_tmp
drwx------ 2 highgo highgo    26  1月  8 11:37 pg_subtrans
drwx------ 2 highgo highgo    10  1月  8 11:37 pg_tblspc
drwx------ 2 highgo highgo    10  1月  8 11:37 pg_twophase
-rw------- 1 highgo highgo     3  1月  8 11:37 PG_VERSION
drwx------ 3 highgo highgo    72  1月  8 11:37 pg_wal
drwx------ 2 highgo highgo    26  1月  8 11:37 pg_xact
-rw------- 1 highgo highgo    88  1月  8 11:37 postgresql.auto.conf
-rw------- 1 highgo highgo 30594  1月  8 11:37 postgresql.conf
-rw------- 1 highgo highgo    69  1月  8 11:37 postmaster.opts
-rw------- 1 highgo highgo    94  1月  8 11:37 postmaster.pid
-rw------- 1 highgo highgo   933  1月  8 11:37 sec_pg.conf
[highgo@localhost data]$ 

IvorySQL 与 Highgo

IvorySQL (Ivory 译为,象牙) 是由瀚高 (Highgo) 发起的基于 PostgreSQL 的衍生开源项目,采用 Apache-2.0 license,100% 兼容原生 PostgreSQL。IvorySQL 导入并增强了 Orafce 扩展插件,以此支持、兼容 Oracle 的诸多特性,如 PACKAGE、数据类型、转换函数等。IvorySQL 增加了 compatible_mode 开关,可以切换 PostgreSQL 和 Oracle 兼容模式。在 Oracle 兼容性方面,IvorySQL 还增加了独有的 PL/iSQL 过程语言,以此来支持 Oracle 的 PL/SQL 语法和 Oracle 风格的 PACKAGES。在即将发布的 IvorySQL v3.0 中,将支持双端口,即端口 5333 用于 IvorySQL 连接,端口 1521 用于 Oracle 模式连接。

2021 年 12 月 15 日,发布了 IvorySQL 的第一个版本。今年 6 月 28 日,发布了 IvorySQL 2.3,下图为目前 IvorySQL 的发布时间线。

ivorysql-timeline.png

参考文档:https://blog.itpub.net/31492144/viewspace-3021687/

作为国产中数据中,相对比较早的厂商,瀚高的发展不如金仓,达梦,高斯db,希望他发展的越来越好。

最后修改时间:2026-01-09 09:55:52
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论