MySQL 8 Clone Plugin의 새로운 기능을 살펴보세요

coldplay.xixi
풀어 주다: 2020-10-29 17:30:24
앞으로
1898명이 탐색했습니다.

mysql 동영상 튜토리얼칼럼에서는 MySQL 8의 새로운 기능인 Clone Plugin

MySQL 8 Clone Plugin의 새로운 기능을 살펴보세요

Clone Plugin이 MySQL 8.0.17에 도입된 주요 기능을 소개합니다. 왜 이 기능을 구현해야 합니까? 개인적으로는 그룹복제를 주로 하는 것 같아요. 그룹 복제에서는 새로운 노드를 추가하고 분산 복구(Distributed Recovery)를 통해 차등 데이터를 완성합니다.

MySQL 8.0.17 이전에는 Binlog라는 한 가지 복구 방법만 지원되었습니다. 하지만 새 노드에 필요한 Binlog가 제거된 경우 현재로서는 백업 도구(XtraBackup, mydumper, mysqldump)를 사용하여 전체 데이터 양을 동기화한 후 분산 복구를 통해 증분 데이터를 동기화할 수 있습니다.

이 방법은 노드 추가 목적도 달성할 수 있지만 여전히 외부 도구의 도움이 필요하므로 일정량의 작업과 사용량 임계값이 필요합니다. 경쟁사인 PXC는 상태 스냅샷 전송(전체 동기화와 유사)을 위해 기본적으로 XtraBackup을 통합하는 반면 MongoDB는 한 단계 더 나아가 전체 데이터를 동기화하기 위해 기본적으로 초기 동기화를 구현한다는 점을 알아야 합니다. 사용 편의성의 관점에서 볼 때 MySQL은 클러스터에 노드를 추가하는 측면에서 경쟁사보다 열등합니다. 고객 경험 측면에서는 아직 개선의 여지가 많습니다.

다행히 MySQL 관계자도 이러한 격차를 인식하고 마침내 MySQL 8.0.17에 Clone Plugin을 구현했습니다. 물론 공무원들에게는 이 기능을 구현하는 것이 어렵지 않습니다. 결국 참고할 수 있는 기성 물리적 백업 도구(MySQL Enterprise Backup)가 있습니다.

이 글은 다음과 같은 측면에서 시작됩니다.

  1. 복제 플러그인 설치
  2. 복제 플러그인 사용
  3. 복제 작업 진행 상황을 확인하는 방법
  4. 복제 데이터를 기반으로 슬레이브 라이브러리를 구축하는 방법
  5. 구현 복제 플러그인 세부 정보
  6. 복제 플러그인의 제한 사항
  7. 복제 플러그인과 XtraBackup의 비교
  8. 복제 플러그인의 매개변수 분석

1. 복제 플러그인 설치

복제 플러그인은 다음 두 가지 설치 방법을 지원합니다.

( 1) 구성 파일 사양

[mysqld] plugin-load-add=mysql_clone.so clone=FORCE_PLUS_PERMANENT复制代码
로그인 후 복사
로그인 후 복사

여기서 클론은 엄밀히 말하면 매개 변수 이름이 아니라 추가할 수 있는 플러그인 이름으로, FORCE_PLUS_PERMANENT가 플러그인의 동작을 제어합니다.

네 가지 값이 있습니다:

  • ON**(**플러그인 활성화)
  • OFF(플러그인 비활성화)
  • FORCE(강제 열기. 플러그인 초기화에 실패하면 MySQL은 시작)
  • FORCE_PLUS_PERMANENT (FORCE 기준에서는 UNINSTALL PLUGIN 명령을 통한 플러그인 제거는 허용되지 않습니다.)

(2) 동적 로딩

[mysqld] plugin-load-add=mysql_clone.so clone=FORCE_PLUS_PERMANENT复制代码
로그인 후 복사
로그인 후 복사

플러그인이 성공적으로 설치되었는지 확인하세요.

mysql> show plugins; ... | clone | ACTIVE | CLONE | mysql_clone.so | GPL | ...复制代码
로그인 후 복사

클론 상태가 "ACTIVE"로 표시되는데, 이는 플러그인이 성공적으로 로딩되었음을 의미합니다.

2. 복제 플러그인 사용

복제 플러그인은 로컬 복제와 원격 복제의 두 가지 복제 방법을 지원합니다.

1. 로컬 복제

로컬 복제는 인스턴스에서 로컬로 시작되며 구문은 다음과 같습니다.

CLONE LOCAL DATA DIRECTORY [=] 'clone_dir';复制代码
로그인 후 복사

그 중 clone_dir은 복제 디렉터리입니다.

아래에서 특정 데모를 살펴보세요.

복제 사용자 만들기

mysql> create user 'clone_user'@'%' identified by 'clone_pass'; mysql> grant backup_admin on *.* to 'clone_user'@'%';复制代码
로그인 후 복사

복제 디렉터리 만들기

# mkdir /data/mysql # chown -R mysql.mysql /data/mysql复制代码
로그인 후 복사

로컬 복제본 만들기

# mysql -uclone_user -pclone_pass mysql> clone local data directory='/data/mysql/3307';复制代码
로그인 후 복사

그 중 "/data/mysql/3307"이 복제 디렉터리로 다음 요구 사항을 충족해야 합니다.

  1. 복제 디렉터리는 절대 경로여야 합니다.
  2. "/data/mysql"이 존재해야 하며 MySQL에는 이에 대한 쓰기 권한이 있습니다.
  3. 3307은 존재할 수 없습니다.

복제 디렉터리 내용 보기

# ll /data/mysql/3307 total 172996 drwxr-x--- 2 mysql mysql 89 May 24 22:37 #clone -rw-r----- 1 mysql mysql 3646 May 24 22:37 ib_buffer_pool -rw-r----- 1 mysql mysql 12582912 May 24 22:37 ibdata1 -rw-r----- 1 mysql mysql 50331648 May 24 22:37 ib_logfile0 -rw-r----- 1 mysql mysql 50331648 May 24 22:37 ib_logfile1 drwxr-x--- 2 mysql mysql 6 May 24 22:37 mysql -rw-r----- 1 mysql mysql 25165824 May 24 22:37 mysql.ibd drwxr-x--- 2 mysql mysql 20 May 24 22:37 slowtech drwxr-x--- 2 mysql mysql 28 May 24 22:37 sys -rw-r----- 1 mysql mysql 10485760 May 24 22:37 undo_001 -rw-r----- 1 mysql mysql 11534336 May 24 22:37 undo_002复制代码
로그인 후 복사

Xtrabackup에 비해 준비할 필요가 없고 바로 시작할 수 있습니다.

# /usr/local/mysql/bin/mysqld --no-defaults --datadir=/data/mysql/3307 --user mysql --port 3307 &复制代码
로그인 후 복사

2. 원격 복제

원격 복제에는 두 개의 인스턴스가 포함됩니다. 그 중 복제할 인스턴스는 Donor이고, 복제된 데이터를 받는 인스턴스는 Recipient입니다. 복제 명령은 수신자에서 시작되어야 하며 구문은 다음과 같습니다.

CLONE INSTANCE FROM 'user'@'host':port IDENTIFIED BY 'password' [DATA DIRECTORY [=] 'clone_dir'] [REQUIRE [NO] SSL];复制代码
로그인 후 복사

그 중 호스트와 포트는 복제할 인스턴스(Donor)의 IP와 포트이고, 사용자와 비밀번호는 복제 사용자와 비밀번호입니다. 위와 같이 Donor의 비밀번호와 backup_admin 권한이 필요합니다. clone_user를 생성했습니다.

DATA DIRECTORY는 백업 디렉터리를 지정합니다. 지정하지 않으면 기본적으로 수신자의 데이터 디렉터리에 복제됩니다.

REQUIRE [NO] SSL, SSL 통신 활성화 여부.

아래에서 구체적인 데모를 살펴보세요.

먼저 Donor 인스턴스에 복제 사용자를 생성하고 복제 플러그인을 로드합니다.

mysql> create user 'donor_user'@'%' identified by 'donor_pass'; mysql> grant backup_admin on *.* to 'donor_user'@'%'; mysql> install plugin clone soname 'mysql_clone.so';复制代码
로그인 후 복사

backup_admin은 복제 작업에 필요한 권한입니다.

다음으로 수신자 인스턴스에 복제 사용자를 생성하고 복제 플러그인을 로드합니다.

mysql> create user 'recipient_user'@'%' identified by 'recipient_pass'; mysql> grant clone_admin on *.* to 'recipient_user'@'%'; mysql> install plugin clone soname 'mysql_clone.so';复制代码
로그인 후 복사

这里的clone_admin,隐式含有backup_admin(阻塞DDL)和shutdown(重启实例)权限。

设置Donor白名单。Recipient只能克隆白名单中的实例。

mysql> set global clone_valid_donor_list = '192.168.244.10:3306';复制代码
로그인 후 복사

设置该参数需要SYSTEM_VARIABLES_ADMIN权限。

在Recipient上发起克隆命令

# mysql -urecipient_user -precipient_pass mysql> clone instance from 'donor_user'@'192.168.244.10':3306 identified by 'donor_pass'; Query OK, 0 rows affected (36.97 sec)复制代码
로그인 후 복사

远程克隆会依次进行以下操作:

**(1)****获取备份锁。**备份锁和DDL互斥。注意,不仅仅是Recipient,Donor上的备份锁同样会获取。

**(2)****DROP用户表空间。**注意,DROP的只是用户数据,不是数据目录,也不包括mysql,ibdata等系统表空间。

**(3)从Donor实例拷贝数据。**对于用户表空间,会直接拷贝,如果是系统表空间 ,则会重命名为xxx.#clone,不会直接替代原文件。

ll /data/mysql/3306/data/ ... -rw-r----- 1 mysql mysql 3646 May 25 07:20 ib_buffer_pool -rw-r----- 1 mysql mysql 3646 May 27 07:31 ib_buffer_pool.#clone -rw-r----- 1 mysql mysql 12582912 May 27 07:31 ibdata1 -rw-r----- 1 mysql mysql 12582912 May 27 07:31 ibdata1.#clone -rw-r----- 1 mysql mysql 50331648 May 27 07:32 ib_logfile0 -rw-r----- 1 mysql mysql 50331648 May 27 07:31 ib_logfile0.#clone ... -rw-r----- 1 mysql mysql 25165824 May 27 07:31 mysql.ibd -rw-r----- 1 mysql mysql 25165824 May 27 07:31 mysql.ibd.#clone ...复制代码
로그인 후 복사

**(4)重启实例。**在启动的过程中,会用xxx.#clone替换掉原来的系统表空间文件。

三、如何查看克隆操作的进度

查看克隆操作的进度主要依托于performance_schema.clone_status和performance_schema.clone_progress这两张表。

首先看看performance_schema.clone_status表。

mysql> select * from performance_schema.clone_status\G *************************** 1\. row *************************** ID: 1 PID: 0 STATE: Completed BEGIN_TIME: 2020-05-27 07:31:24.220 END_TIME: 2020-05-27 07:33:08.185 SOURCE: 192.168.244.10:3306 DESTINATION: LOCAL INSTANCE ERROR_NO: 0 ERROR_MESSAGE: BINLOG_FILE: mysql-bin.000009 BINLOG_POSITION: 665197555 GTID_EXECUTED: 59cd4f8f-8fa1-11ea-a0fe-000c29f66609:1-560 1 row in set (0.06 sec)复制代码
로그인 후 복사

顾名思义,该表记录了克隆操作的当前状态。

其中,

  • **PID:**Processlist ID。对应show processlist中的Id,如果要终止当前的克隆操作,执行kill processlist_id命令即可。

  • **STATE:**克隆操作的状态,Not Started(克隆尚未开始),In Progress(克隆中),Completed(克隆成功),Failed(克隆失败)。如果是Failed状态,ERROR_NO,ERROR_MESSAGE会给出具体的错误编码和错误信息。

  • **BEGIN_TIME,END_TIME:**克隆操作开始,结束时间。

  • **SOURCE:**Donor实例的地址。

  • **DESTINATION:**克隆目录。“LOCAL INSTANCE”代表当前实例的数据目录。

  • **GTID_EXECUTED,BINLOG_FILE(BINLOG_POSITION):**克隆操作结束时,主库已经执行的GTID集合,及一致性位置点。可利用这些信息来搭建从库。

接下来看看performance_schema.clone_progress表。

mysql> select * from performance_schema.clone_progress; +------+-----------+-----------+----------------------------+----------------------------+---------+-----------+-----------+-----------+------------+---------------+ | ID | STAGE | STATE | BEGIN_TIME | END_TIME | THREADS | ESTIMATE | DATA | NETWORK | DATA_SPEED | NETWORK_SPEED | +------+-----------+-----------+----------------------------+----------------------------+---------+-----------+-----------+-----------+------------+---------------+ | 1 | DROP DATA | Completed | 2020-05-27 07:31:28.581661 | 2020-05-27 07:31:35.855706 | 1 | 0 | 0 | 0 | 0 | 0 | | 1 | FILE COPY | Completed | 2020-05-27 07:31:35.855952 | 2020-05-27 07:31:58.270881 | 2 | 482463294 | 482463294 | 482497011 | 0 | 0 | | 1 | PAGE COPY | Completed | 2020-05-27 07:31:58.271250 | 2020-05-27 07:31:58.719085 | 2 | 10977280 | 10977280 | 11014997 | 0 | 0 | | 1 | REDO COPY | Completed | 2020-05-27 07:31:58.720128 | 2020-05-27 07:31:58.930804 | 2 | 465408 | 465408 | 465903 | 0 | 0 | | 1 | FILE SYNC | Completed | 2020-05-27 07:31:58.931094 | 2020-05-27 07:32:01.063325 | 2 | 0 | 0 | 0 | 0 | 0 | | 1 | RESTART | Completed | 2020-05-27 07:32:01.063325 | 2020-05-27 07:32:59.844119 | 0 | 0 | 0 | 0 | 0 | 0 | | 1 | RECOVERY | Completed | 2020-05-27 07:32:59.844119 | 2020-05-27 07:33:08.185367 | 0 | 0 | 0 | 0 | 0 | 0 | +------+-----------+-----------+----------------------------+----------------------------+---------+-----------+-----------+-----------+------------+---------------+ 7 rows in set (0.00 sec)复制代码
로그인 후 복사

该表记录了克隆操作的进度信息。

  • **STAGE:**一个克隆操作可依次细分为DROP DATA,FILE COPY,PAGE COPY,REDO COPY,FILE SYNC,RESTART,RECOVERY等7个阶段。当前阶段结束了才会开始下一个阶段。

  • **STATE:**当前阶段的状态。有三种状态:Not Started,In Progress,Completed。

  • **BEGIN_TIME,END_TIME:**当前阶段的开始时间和结束时间。

  • **THREADS:**当前阶段使用的并发线程数。

  • **ESTIMATE:**预估的数据量。

  • **DATA:**已经拷贝的数据量。

  • **NETWORK:**通过网络传输的数据量。如果是本地克隆,该列的值为0。

  • **DATA_SPEED,NETWORK_SPEED:**当前数据拷贝的速率和网络传输的速率。

    注意,是当前值。

四、如何基于克隆数据搭建从库

在前面,我们介绍过performance_schema.clone_status表,该表会记录Donor实例的一致性位置点信息。我们可以利用这些信息来搭建从库。

mysql> select * from performance_schema.clone_status\G *************************** 1\. row *************************** ... BINLOG_FILE: mysql-bin.000009 BINLOG_POSITION: 665197555 GTID_EXECUTED: 59cd4f8f-8fa1-11ea-a0fe-000c29f66609:1-560 1 row in set (0.06 sec)复制代码
로그인 후 복사

这里,区分两种场景,GTID复制和基于位置点的复制。

1、GTID复制

mysql> CHANGE MASTER TO MASTER_HOST = 'master_host_name', MASTER_PORT = master_port_num, ... MASTER_AUTO_POSITION = 1; mysql> START SLAVE;复制代码
로그인 후 복사

需要注意的是,无需额外执行set global gtid_purged操作。通过克隆数据启动的实例,gtid_purged已经初始化完毕。

mysql> show global variables like 'gtid_purged'; +---------------+--------------------------------------------+ | Variable_name | Value | +---------------+--------------------------------------------+ | gtid_purged | 59cd4f8f-8fa1-11ea-a0fe-000c29f66609:1-560 | +---------------+--------------------------------------------+ 1 row in set (0.00 sec)复制代码
로그인 후 복사

2、基于位置点的复制

这里,同样要区分两种场景。

场景1,Recipient要作为Donor的从库。

mysql> SELECT BINLOG_FILE, BINLOG_POSITION FROM performance_schema.clone_status; mysql> CHANGE MASTER TO MASTER_HOST = 'master_host_name', MASTER_PORT = master_port_num, ... MASTER_LOG_FILE = 'master_log_name', MASTER_LOG_POS = master_log_pos; mysql> START SLAVE;复制代码
로그인 후 복사

其中,

master_host_name,master_port_num:Donor实例的IP和端口。

master_log_name,master_log_pos:performance_schema.clone_status 中的BINLOG_FILE, BINLOG_POSITION。

场景2,Donor本身就是一个从库,Recipient要作为Donor主库的从库。

mysql> SELECT MASTER_LOG_NAME, MASTER_LOG_POS FROM mysql.slave_relay_log_info; mysql> CHANGE MASTER TO MASTER_HOST = 'master_host_name', MASTER_PORT = master_port_num, ... MASTER_LOG_FILE = 'master_log_name', MASTER_LOG_POS = master_log_pos; mysql> START SLAVE;复制代码
로그인 후 복사

其中,

master_host_name,master_port_num:Donor主库的IP和端口。

master_log_name,master_log_pos:mysql.slave_relay_log_info中的Master_log_name,Master_log_pos(分别对应 SHOW SLAVE STATUS 中的 Relay_Master_Log_File,Exec_Master_Log_Pos)。

在搭建从库时,建议设置--skip-slave-start。该参数默认为OFF,实例启动后,会自动执行START SLAVE操作。

如果Donor是个从库,Recipient会基于mysql.slave_master_info,mysql.slave_relay_log_info中的信息自动建立复制,很多时候,这未必是我们的预期行为。

五、Clone Plugin的实现细节

克隆操作可细分为以下5个阶段。

[INIT] ---> [FILE COPY] ---> [PAGE COPY] ---> [REDO COPY] -> [Done]复制代码
로그인 후 복사

**1、INIT:**初始化一个克隆对象。

**2、FILE COPY:**拷贝所有数据文件。在拷贝之前,会记录一个LSN,作为“CLONE START LSN”,这个LSN其实是当前CHECKPOINT的LSN,同时启动“Page Tracking”特性。

“Page Tracking”会跟踪“CLONE START LSN”之后被修改的页,具体来说,会记录该页的Tablespace ID和page ID。数据文件拷贝结束后,会将当前CHECKPOINT的LSN记为“CLONE FILE END LSN”。

**3、PAGE COPY:**拷贝“CLONE START LSN”和“CLONE FILE END LSN”之间的页,在拷贝之前,会对这些页进行排序-基于Tablespace ID和page ID,尽量避免拷贝过程中出现随机读写。同时,开启“Redo Archiving”特性。

“Redo Archiving”会在后台开启一个归档线程将Redo文件中的内容按Chunk拷贝到归档文件中。通常来说,归档线程的拷贝速度会快于Redo日志的生成速度。即使慢于,在写入新的Redo日志时,也会等待归档线程完成拷贝,不会出现还未拷贝的Redo日志被覆盖的情况。当所有修改的页拷贝完毕后,会获取实例的一致性位置点信息,此时的LSN记为“CLONE LSN”。

4、REDO COPY:拷贝归档文件中“CLONE FILE END LSN”与“CLONE LSN”之间的Redo日志。

**5、Done:**调用snapshot_end()销毁克隆对象。

六、Clone Plugin的限制

1、克隆期间,不允许执行DDL命令。同样,DDL会阻塞克隆命令的执行

2、Clone Plugin不会拷贝Donor的配置参数。

3、Clone Plugin不会拷贝Donor的二进制日志文件。

4、Clone Plugin只会拷贝InnoDB表的数据,对于其它存储引擎的表,只会拷贝表结构。

5、Donor实例中如果有表通过DATA DIRECTORY指定了绝对路径,在进行本地克隆时,会提示文件已存在。在进行远程克隆时,绝对路径必须存在且有可写权限。

6、不允许通过MySQL Router连接Donor实例。

7、执行CLONE INSTANCE操作时,指定的Donor端口不能为X Protocol端口。

除此之外,在进行远程克隆时,还会进行如下检查:

  • MySQL版本(包括小版本)必须一致,且支持Clone Plugin。
ERROR 3864 (HY000): Clone Donor MySQL version: 8.0.20 is different from Recipient MySQL version 8.0.19.复制代码
로그인 후 복사
  • 主机的操作系统和位数(32位,64位)必须一致。两者可根据version_compile_os,version_compile_machine参数获取。
  • Recipient必须有足够的磁盘空间存储克隆数据。
  • 字符集(character_set_server),校验集(collation_server),character_set_filesystem必须一致。
  • innodb_page_size必须一致。会检查innodb_data_file_path中ibdata的数量和大小。
  • 目前Clone Plugin(8.0.20)的实现,无论是Donor,还是Recipient,同一时间,只能执行一个克隆操作。后续会支持多个克隆操作并发执行。
ERROR 3634 (HY000): Too many concurrent clone operations. Maximum allowed - 1.复制代码
로그인 후 복사
  • Recipient需要重启,所以其必须通过mysqld_safe或systemd等进行管理。如果是通过mysqld进行启动,实例关闭后,需要手动启动。
ERROR 3707 (HY000): Restart server failed (mysqld is not managed by supervisor process).复制代码
로그인 후 복사
  • ACTIVE状态的Plugin必须一致。

七、Clone Plugin与XtraBackup的对比

1、在实现上,两者都有FILE COPY和REDO COPY阶段,但Clone Plugin比XtraBackup多了一个PAGE COPY,由此带来的好处是,Clone Plugin的恢复速度比XtraBackup更快。

2、XtraBackup没有Redo Archiving特性,有可能出现未拷贝的Redo日志被覆盖的情况。

3、GTID下建立复制,无需额外执行set global gtid_purged操作。

八、Clone Plugin的参数解析

  • clone_autotune_concurrency是否自动调节克隆过程中并发线程数的数量,默认为ON,此时,最大线程数受clone_max_concurrency参数控制。若设置为OFF,则并发线程数的数量将是固定的,同clone_max_concurrency参数一致。该参数的默认值为16。
  • clone_buffer_size本地克隆时,中转缓冲区的大小,默认4M。缓冲区越大,备份速度越快,相应的,对磁盘IO的压力越大。
  • clone_ddl_timeout克隆操作需要获取备份锁(Backup Lock)。如果在执行CLONE命令时,有DDL在执行,则CLONE命令会被阻塞,等待获取备份锁(Waiting for backup lock)。等待的最大时长由clone_ddl_timeout参数决定,默认300(单位秒)。如果在这个时间内还没获取到锁,CLONE命令会失败,且提示“ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction”。

需要注意的是,如果在执行DDL时,有CLONE命令在执行,DDL同样会因获取不到备份锁被阻塞,只不过,DDL操作的等待时长由lock_wait_timeout参数决定,该参数的默认值为31536000s,即365天。

  • clone_enable_compression원격 복제, 데이터 전송 시 압축 활성화 여부. 압축을 켜면 네트워크 대역폭을 절약할 수 있지만 그에 따라 CPU 사용량도 늘어납니다.
  • clone_max_data_bandwidth원격 복제 중에 허용되는 최대 데이터 복사 속도(단위: MiB/s). 기본값은 0이며 제한이 없습니다. 여기서 제한은 단일 스레드의 복사 속도일 뿐입니다. 여러 스레드가 병렬로 복사되는 경우 실제 최대 복사 속도는 clone_max_data_bandwidth*스레드 수입니다.
  • clone_max_network_bandwidth원격 복제 중에 허용되는 최대 네트워크 전송 속도(단위: MiB/s). 기본값은 0이며 제한이 없습니다. 네트워크 대역폭에 병목 현상이 있는 경우 이 매개변수를 사용하여 속도를 제한할 수 있습니다.
  • clone_valid_donor_list기부자 화이트리스트를 설정하면 화이트리스트에 지정된 인스턴스만 복제할 수 있습니다.
  • clone_ssl_ca, clone_ssl_cert, clone_ssl_keySSL 관련.

관련 무료 학습 권장사항:mysql 비디오 튜토리얼

위 내용은 MySQL 8 Clone Plugin의 새로운 기능을 살펴보세요의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.im
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!