`
yangzb
  • 浏览: 3482080 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
阅读更多

1.背景介绍
  复制是为了满足用户对数据库中重要的表的复制以及数据分发和数据集中的要求。
  DM数据库管理系统能够让用户建立不同级别复制关系,当用户在主服务器上进行表操作时,系统将主服务器中表上的所有操作复制到从服务器中对应的表中。
2.系统总体结构
2.1 异步复制执行流程

2.2 安全机制
2.2.1 功能
1.从服务器的登录检查,由用户指定登录从服务器的登录名和密码。
2.如果没有指定登录名与密码,或者密码错误,主服务器与从服务器建立SNET连接时,将会报错。
3.一台从服务器,只能指定一个登录名与密码,从服务器上的所有操作都使用此登录对应的用户进行权限检查。
4.登录名、密码等信息保存在主服务器。
5.创建复制登录操作,将会登录指定的从服务器验证LOGIN和PASSWORD的正确性,从服务器返回加密后的PASSWORD字符串,主服务器将加密后的密码信息保留在SYSDUPLOGINS系统表中。
6.一个SNET连接,在从服务器会创建一个对应的SESSION,此SESSION的所有操作使用LOGIN对应的用户进行权限检查(原有实现是:从服务器操作一律使用SYSDBA身份进行,也就是可以进行任何操作)
2.2.2 创建复制登录处理
1.检查输入参数的正确性
2.调用字典封锁,防止其他用户进行操作,保证复制登录链表完整性
3.检查是否已经创建了相同从服务器上的复制登录
4.登录从服务器,并获取加密后的密码
5.构造复制登录内存对象,插入复制登录信息到SYSDUPLOGINS系统表
2.2.3 删除复制登录处理
1.检查输入参数的正确性
2.调用字典封锁,防止其他用户进行操作,保证复制登录链表完整性
3.检查是否存在指定的复制登录
4.释放SNET链表中对应此复制登录的SNET对象
5.释放复制登录内存对象,并从SYSDUPLOGINS系统表中删除此复制登录信息
2.2.4 权限检查处理
1.主服务器填充LOGIN、PASSWORD等信息,发送消息到从服务器
2.从服务器检查以LOGIN对应的用户身份创建SESSION
3.在从服务器的所有操作,使用此用户身份进行权限检查
2.3 站点、库、模式、表复制
2.3.1. 实现
为了支持站点、DB、模式级别的数据复制,需要修改的代码主要集中在主服务器相关处理,从服务器不做任何改动。
根据现有的复制执行流程,如果保证主服务器上的所有非系统表的数据修改,所生成的UREC按照同步复制流程处理,发送DREC到从服务器时,处理站点上的复制关系,就可以支持站点级复制。
如果保证主服务器上指定库的所有非系统表的数据修改,所生成的UREC按照同步复制流程处理,发送DREC到从服务器时,处理库上的复制关系,就可以支持了库级复制。
如果保证主服务器上的指定模式下的所有非系统表的数据修改,所生成的UREC按照同步复制流程处理,发送DREC到从服务器时,处理模式上的复制关系,就可以支持模式级的复制。
上述3中类型的复制,同样也是以事务为单位进行处理,同样由同步复制机制保证事务一致性。
具体修改如下:
1.增加创建、删除各种级别复制关系的系统函数;
2.修改REPORT生成INSERT、DELETE、UPDATE回滚记录UREC的处理,原有系统只处理了表复制,增加模式、DB、站点复制关系的判断:
 a)保证回滚记录包含了所有更新的数据内容(正常的UREC可能只包含PK等信息,某些字段内容不包含在UREC中)
 b)标记当前事务为复制事务
 c)设置当前回滚记录TYPE,为涉及同步复制事务
 d)对涉及同步复制的BLOB数据修改,不做优化,需要全部生成回滚记录
 e)其他执行流程与普通表相同
3.主服务器事务提交时,判断当前事务是否为同步复制事务,如果是,根据UREC内容,生成DREC,并将生成的DREC通过SNET发送往从服务器
4.从服务器执行完成后,返回结果到主服务器
5.主服务器根据从服务器返回,决定事务提交成功或失败
2.4 异步复制
2.4.1. 目的
为了适应数据库集群异常处理的要求,以及简化异步复制处理流程,提高异步复制可靠性、实用性。
异步复制功能,应该满足一下条件:
1.只需要配置DM服务器,即可进行异步复制,不再需要DUP复制控制器
2.应支持从服务器上的用户权限管理
3.应支持一对多和多对一异步复制
4.应支持级联异步复制
5.应支持对称异步复制
6.应支持环形异步复制
7.应支持大数据对象的异步复制
8.应支持表级、模式级、库级和站点级的异步复制
9.应支持指定时间和指定时间间隔两种方式的异步复制
10.应提供出错处理,用户可以查询执行情况
2.4.2. 功能
1. 由DM服务器承担原DUP控制器功能
2. 取消逻辑日志文件功能
3. 异步复制数据以DREC形式保存在主服务器的系统表SYSASYNCDRECS中,同时需要保存操作的来源站点信息,以支持对称异步复制
4. 异步复制时间间隔信息保存在SYSDUPLOGINS系统表中
5. 对应每个复制登录,主服务器生成一个线程,此线程根据设定,定期将DREC数据发送到从服务器
6. 主服务器以事务为单位发送DREC到从服务器
7. 主服务器接到从服务器返回后,删除系统表中相应的DREC记录
8. 从服务器负责解析DREC并执行,处理流程与同步复制类似
2.4.3异步复制流程
  主服务器发送DREC信息与同步复制处理类似,需要将站点信息一并发送到从服务器,从服务器根据这些站点信息判断,是否形成回路,以决定是否执行当前事务。
1. REPORT操作流程与同步复制类似
2. 事务提交流程修改:
 a) 取消写逻辑日志文件操作
 b) PURGE操作过程中,根据UREC生成DREC,保存到系统表SYSASYNCDRECS系统表中。由于DREC包含了UREC和从表对应的 DB、SCHEMA、TABLE等信息,记录长度有可能超过块长一半,不符合现有系统的插入条件,因此,一条记录有可能需要拆分成两条插入。
3. 主服务器的异步复制线程,根据设置时间、时间间隔定时从SYSASYNCDRECS系统表获取数据,建立与从服务器的SNET连接
4. 异步复制线程,以事务为单位发送DREC数据到从服务器
5. 从服务器接收到DREC数据后,解析、执行结束后,返回主服务器
6. 主服务器判断执行结果,成功,则删除SYSASYNCDRECS系统表中数据;失败,转入错误处理
7. 依次执行4~6,直至所有数据发送完成
8. 出错处理:从服务器执行报错,将返回的出错信息记录在SYSASYNCERRORS系统表中。删除SYSASYNCDRECS系统表中出错事务的DREC记录。
2.4.4 存在问题
(1).数据完整性:
  从服务器执行成功,但主服务器还没有删除DREC记录时,系统或网络异常,某个事务可能在从服务器多次执行。
(2).没有提供冲突检测、干预机制,在多对一或对称情况下,虽然从服务器执行成功,但无法保证数据一致性(正确性)。应在系统规划中避免类似情况。
  异步复制信息记录在主服务器,并以事务为单位发送到从服务器,从服务器接收到数据后立即执行。此方法的优点是与同步复制的机制基本保持一致,实现相对简单。但由于从服务器是被动接收数据,无法进行主动的冲突检测。考虑下列实际应用:
  某大型超市发行了购物卡,卡信息保存在中心主服务器上,各超市有卡信息的本地拷贝,但日常操作,不直接连接中心服务器,而是修改超市本地服务器。假设 用户U的卡上余额为1000块,某日上午在A超市消费了100块,A超市本地服务器上的余额变为900块;下午,U又在B超市消费了50块,B超市本地服 务器上的余额为950块;晚上数据汇总到中心主服务器时,该如何处理U的帐户余额?似乎ORACLE等冲突解决机制也无法适应此场景。
2.5 死锁检测机制
2.5.1. 目的
  防止出现全局死锁,提高死锁检测效率和事务成功率。
2.5.2. 功能
  修改后的死锁检测机制,采用全局死锁检测和超时检测相结合的方法来防止全局死锁的出现。
  全局死锁检测,构造全局事务的等待队列,使用这个全局等待队列进行死锁检测。A站点的事务X处于PRE_COMMIT状态,发送DREC数据到B站 点,并等待B站点的同步复制从事务X’执行返回,此时,X事务等待X’事务,X’事务的全局等待事务链表中包含A站点的X事务。如果B站点中,X’事务等 待Y事务,然后Y事务进入PRE_COMMIT状态,发送DREC数据到A站点,并等待A站点的同步复制从事务Y’执行返回,此时,Y事务等待Y’事务; 并且X、X’间接等待Y ’事务,Y’事务的全局等待链表中包含X、X’、Y事务。Y’事务上锁失败,进入锁等待时,检查是否发生死锁,先检查本地事务是否形成死锁,如果没有,则 进一步检查全局事务是否形成死锁,如果Y’事务要等待X事务(直接等待或间接等待),则形成了全局死锁。
  全局死锁检测,并不能完全避免全局死锁的发生。上节描述的环境下,如果Y先进入PRE_COMMIT状态,X’事务后等待Y事务,则无法检测到全局死锁,但实际形成了全局死锁。这种情况,可以由下节描述的超时检测,防止出现全局死锁。
  超时检测是指,同步复制从事务(X’和Y’事务),如果锁等待超过1秒,则认为发生了全局死锁,主动回滚从事务。采用超时检测机制,还可以有效解决问题1,X’事务等待超过1秒后,将被回滚,X事务回滚,检查点执行成功,A站点恢复正常。
(1) 全局死锁检测
  全局死锁检测修改,主要涉及事务提交和死锁检测模块。
  事务提交修改,假设X事务进入PRE_COMMIT或PRE_COMMIT2状态:
1.进入核心临界区
2.扫描全局事务链表,找出所有直接或间接等待X事务的从事务
3.将符合条件的从事务信息,以及从事务的全局等待事务信息填入到结束DREC记录中,并发送从服务器
4.从服务器的X’事务,解析结束DREC记录,构造X’事务的全局等待链表
死锁检测模块修改:
1.检查本地事务是否发生死锁
2.检测X’事务事务,是否在等待X’事务全局等待链表中的事务,如果有,则认为发生了死锁
(2) 超时检测修改
  超时检测修改,主要涉及调度线程和工作线程。
全局事务死锁检测功能:
1.进入核心临界区
2.找出处于锁等待状态超过1秒的从事务
3.设置从事务的WAITING锁状态为不等待,防止此事务被其他事务唤醒
4.生成全局事务回滚任务,加入任务队列
5.退出核心临界区
自主死锁回滚处理:
1.设置从事务的error_number 为EC_RN_DEADLOCK
2.唤醒CTX
3.设置事务状态为ACTIVE
4.调用ctx_set_errcode设置错误码EC_RN_DEADLOCK
5.进入正常的CTX执行流程,系统自动回滚从事务,并返回主服务器
2.5.3 检查点问题
  采用全局事务超时死锁检测机制后,还不能完全解决问题1。考虑下列情况:A站点的X事务处于PRE_COMMIT状态,与此同时,B站点的Y事务也处 在PRE_COMMIT状态,A、B站点同时进入检查点处理,暂停所有工作线程,等待处理X、Y的工作线程执行结束,但X、Y发送到B、A站点的任务一直 得不到处理,导致系统挂起,无法响应用户请求。如果将服务器配置成异步检查点,此问题不复存在。但系统需要保证,在服务器配置成同步检查点情况下,系统不 至被挂起。此问题的解决方案如下:
1.系统进入同步检查点后,设置一个同步检查点标记;
2.调度线程检查到同步检查点标记后,检查COP任务队列,发现有同步复制事务,将此COP任务从队列中移出,并发送EC_SNET_FAIL消息回主服务器;
3.主事务收到返回消息后,snet_recv函数判断返回值为EC_SNET_FAIL,释放snet上的port对象;再根据主服务器事务状态,处理如下:
 A)TRX_PRE_COMMIT:回滚事务
 B)TRX_PRE_COMMIT2:回滚事务
 C)TRX_COMMITING:继续提交
 D)TRX_ROLLING:继续回滚
  按照以上步骤,A站点X事务发送到B站点的同步复制请求,将被B站点的调度线程返回,而后X事务回滚,X事务结束,A站点检查点执行成功。 同???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????,B 站点的Y事务,也被回滚,检查点执行成功。系统恢复正常。
3.场景应用
  以下通过在一个简单应用中使用异步复制功能,对异步复制的配置和执行过程进行说明。
3.1. 应用环境说明
  假定,某超市,每天会将各超市营业网点的销售数据发往公司服务器,以便对销售数据进行统计、分析。
应用环境:
 某超市公司数据库服务器:SERVER_CS(223.254.102.100)
 某超市营业网点A数据库服务器:SERVER_A(223.254.102.1)
 某超市营业网点B数据库服务器:SERVER_B(223.254.102.2)

数据对象环境:
 某超市公司数据库服务器数据表:SYSTEM.SYSDBA.销售记录
 某超市营业网点A数据库服务器数据表:SYSTEM.SYSDBA.销售记录_A
 某超市营业网点B数据库服务器数据表:SYSTEM.SYSDBA.销售记录_B

 通过对营业网点A、B数据库服务器中的销售记录表,建立到公司服务器销售记录表的异步表级复制,并设定在每天的0:0:0.0时,将数据发往公司服务器,以便公司能够在正常上班时间,完成对销售数据的统计和分析。
3.2 对象建立
  某超市公司数据库服务器,以SYSDBA/SYSDBA登录执行:
 CREATE TABLE 销售记录 (CS_ID INT ,商品编号 VARCHAR(100),商品名称 VARCHAR(1000),销售量 INT, 销售总额 MONEY ,CLUSTER PRIMARY KEY(CS_ID, 商品编号));

  某超市营业网点A数据库服务器,以SYSDBA/SYSDBA登录执行:
 CREATE TABLE 销售记录_A (CS_ID INT ,商品编号 VARCHAR(100),商品名称 VARCHAR(1000),销售量 INT, 销售总额 MONEY
,CLUSTER PRIMARY KEY(CS_ID, 商品编号));
  某超市营业网点B数据库服务器,以SYSDBA/SYSDBA登录执行:
 CREATE TABLE 销售记录_B (CS_ID INT ,商品编号 VARCHAR(100),商品名称 VARCHAR(1000),销售量 INT, 销售总额 MONEY
,CLUSTER PRIMARY KEY(CS_ID, 商品编号));

3.3. 异步复制配置
3.3.1 异步复制登录设置
  在建立异步复制前,先建立异步复制需要使用的登录信息。
某超市营业网点A数据库服务器,以SYSDBA/SYSDBA登录执行:
 CALL SP_CREATE_REPLICATE_LOGIN('223.254.102.100',12345,'SYSDBA','SYSDBA');
  某超市营业网点B数据库服务器,以SYSDBA/SYSDBA登录执行:
 CALL SP_CREATE_REPLICATE_LOGIN('223.254.102.100',12345,'SYSDBA','SYSDBA');
3.3.2异步复制设置
  建立各营业网点销售记录表到公司服务器销售记录的异步复制关系。
  某超市营业网点A数据库服务器,以SYSDBA/SYSDBA登录执行:
 CALL SP_CREATE_TABLE_REPLICATE('SYSTEM.SYSDBA.销售记录_A','SYSTEM.SYSDBA.销售记录','223.254.102.100','ASYNC')
  某超市营业网点B数据库服务器,以SYSDBA/SYSDBA登录执行:
 CALL SP_CREATE_TABLE_REPLICATE('SYSTEM.SYSDBA.销售记录_B','SYSTEM.SYSDBA.销售记录','223.254.102.100','ASYNC')
3.3.3 异步时间设置
  DM601设置异步复制的执行时间有两种方式:一种是定时复制,在每一天固定时段执行复制操作;一种是时间间隔复制,设置复制后,每间隔一定的时间段就执行复制。
  在这个应用中,每天固定在0:0:0.0执行异步复制操作,所以我们使用定时复制。
  某超市营业网点A数据库服务器,以SYSDBA/SYSDBA登录执行:
CALL SP_SET_ASYNC_REPLICATE_TIME('223.254.102.100','0:0:0.0');
  某超市营业网点B数据库服务器,以SYSDBA/SYSDBA登录执行:
CALL SP_SET_ASYNC_REPLICATE_TIME('223.254.102.100','0:0:0.0');
  通过以上步骤,完成整个应用环境的异步复制的配置过程。
3.3.4 执行
  某超市营业网点A数据库服务器,以SYSDBA/SYSDBA登录执行:
 INSERT INTO 销售记录_A VALUES (1,'A001', 'A001',100,456.54);
 INSERT INTO 销售记录_A VALUES (1,'B002','B002',7,864.5);
 INSERT INTO 销售记录_A VALUES (1,'C007','C007',34,87.0);

  某超市营业网点B数据库服务器,以SYSDBA/SYSDBA登录执行:
 INSERT INTO 销售记录_B VALUES (2, 'A001','A001',89,358.25);
 INSERT INTO 销售记录_B VALUES (2, 'B001','B001',11,34.25);
 INSERT INTO 销售记录_B VALUES (2, 'D011','D011',77,7848.58);

  每天0:0:0.0后,以SYSDBA/SYSDBA登录某超市公司数据库服务器,查询销售记录:
  SELECT * FROM 销售记录;
结果显示为:
 (1,'A001', 'A001',100,456.54);
 (1,'B002','B002',7,864.5);
 (1,'C007','C007',34,87.0);
 (2, 'A001','A001',89,358.25);
 (2, 'B001','B001',11,34.25);
 (2, 'D011','D011',77,7848.58);

4结束语
  通过第三节的操作,演示了异步复制中最基本的操作。
  通过以上操作可以发现,异步复制可以比较灵活、方便、快捷的将数据在各个数据库之间传递,为应用在配置、管理、安全、操作、维护等等各个方面,提供一种灵活、多样的手段,使应用更好的服务于现实工作中。
  当然,此文,仅以一种简单的方式,向大家介绍异步复制的功能。异步复制的功能决不仅仅局限于上面简单的例子。
DM601实现了多样的异步复制功能。不仅提供表级异步复制,还支持诸如:模式级、数据库级、站点级异步复制等;支持的异步复制的方式也分为定时复制和时 间间隔复制;支持对异步复制状态的设定;支持多种异步复制方式等等。异步复制操作涉及多个数据库之间的协调和一致,具有一定的复杂性,为了更好的使用异步 复制,在具体的操作过程中还存在一定的限制。
  如对异步复制功能有兴趣,想了解更多有关异步复制的功能和操作,可以查阅DM异步复制相关文档。

分享到:
评论

相关推荐

    dm分区详解\dm教程

    dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解dm分区详解...

    施耐德DM2000仪表说明书 DM2350N DM2355N-仪表-用户手册 v1.5.3

    手册强调了合法使用和版权保护,未经施耐德电气书面许可,不得复制或传播手册内容,尤其是用于商业目的。 安全信息部分是手册的核心,强调了使用设备时必须遵守的安全警告和预防措施。手册中的符号系统用于指示不同...

    DM test.rar_-baijiahao_DM 检验_DM-test_DM检验_dmtest检验

    《DM测试:深入理解及其在统计与AI中的应用》 DM测试,全称为Dempster-Maier测试,是统计学、数学以及人工智能领域中一个重要的评估模型性能和比较不同模型优劣的方法。该测试源自概率理论中的证据理论,由Dempster...

    万用表DM3058编程手册

    DM3058/DM3058E 数字万用表 编程手册。本手册用于指导用户使用远程命令控制 RIGOL DM3058/DM3058E 万用表进行测量工作。 本手册包含以下章节: 第 1 章 概述 对命令集的使用方法进行概述。 第 2 章 通用命令...

    DM9051驱动源码介绍

    "DM9051 驱动源码介绍" 本文档将对 DM9051 驱动源码进行详细的介绍,包括寄存器初始化、接口函数封装等内容。DM9051 是基于 SPI 接口的以太网 MAC+PHY 集成 IC,广泛应用于嵌入式 ARM、MCU 单片机系统进行以太网...

    美国康耐视DM150/DM260系列用户手册

    DataMan 150/260 系列...这可轻松改装到现有的 DataMan 100/200 应用程序中,无需适配器板,也无需更改安美国康耐视DM150/DM260系列用户手册,适用与COGNEX,DM150,DM152.DM262.DM262系列读码器的配件,选型,设置等用途,

    Java连接达梦数据库驱动dm_jdbc

    Java连接达梦数据库驱动dm_jdbc: dm_jdbc\com.dameng.floader.jar dm_jdbc\com.dameng.impexp.jar dm_jdbc\Dm7Dictionary.jar dm_jdbc\Dm7JdbcDriver14.jar dm_jdbc\Dm7JdbcDriver15.jar dm_jdbc\Dm7JdbcDriver16....

    DM码的识别

    在IT行业中,DM码(Data Matrix Code)是一种二维条形码标准,用于存储大量数据,尤其在工业自动化、电子元器件标识等领域应用广泛。DM码的识别是图像处理和计算机视觉领域的重要研究课题,它涉及到图像采集、预处理...

    dm500 dm800 dm800se 新蕾4 工具包集合

    dm500 dm800 dm800se 新蕾4 工具包集合

    dm542_C51_coverh65_dm542_51单片机DM542_57步进电机;_

    本项目主要关注如何使用51单片机通过DM542驱动57或42步进电机,实现对电机的精确控制,包括速度调节、方向切换以及启停控制。 首先,我们要了解51单片机的基本结构。51系列单片机是由Intel公司开发的,基于8051内核...

    STM32F103C8T6+DM9051实现SPI转以太网功能板AD原理图+lwip-DM9051软件源码.zip

    STM32F103C8T6+DM9051实现SPI转以太网功能板AD原理图+lwip_DM9051软件源码 void mem_shw(char *hdstr, uint8_t *payload, u16_t len) { u16_t i; if ((unsigned int)hdstr){ DM9051_TRACE(mem_str[(int)...

    DM3068数字万用表编程手册

    本手册用于指导用户使用SCPI命令通过远程接口编程控制DM3068数字万用表。 DM3068数字万用表可通过USB、LAN、RS232、GPIB等远程接口与PC通信。欲了解更多关于各种远程接口的使用,请参考《DM3068用户手册》。本手册...

    DM码生成源码

    通常,它们会处理依赖关系、注册表项以及文件复制等安装过程。 4. `ExpoSYs`:这是一个可能的项目文件夹,里面包含了源代码、资源文件和其他与项目相关的文件。具体的文件结构和内容需要进一步查看才能确定,但通常...

    dm800 dm800se 新蕾4 电脑PC端直播收看软件

    标题中的“dm800”、“dm800se”和“新蕾4”都是与数字电视接收设备相关的关键词,通常指的是卫星电视接收器或网络电视机顶盒。这些设备允许用户通过连接到互联网或卫星信号来接收电视节目。在本案例中,“dm800”和...

    DM9161参考电路图

    **DM9161参考电路图详解** DM9161是一款高性能的以太网物理层(PHY)芯片,主要用于实现设备与以太网之间的物理连接。它支持10/100/1000Mbps的速度,并且具有全双工和半双工操作的能力,同时具备自动协商和故障检测...

    nacos适配dm达梦数据库

    2. **数据库脚本**:Nacos提供了一个专门针对DM达梦的数据库创建脚本,即`nacos-dm/conf/nacos-dm.sql`。这个脚本包含了创建Nacos所需表结构、索引以及初始化数据的SQL语句。运行此脚本前,需要确保你有对DM数据库的...

    magisk面具模块 关闭dm校验

    【标题】"Magisk面具模块 关闭dm校验" 是一个针对Android系统的模块,它主要用于禁用设备的dm-verity功能。dm-verity是Android系统中的一个安全特性,旨在防止设备启动时加载篡改过的系统文件,从而保护系统免受恶意...

    dm9161,dm9161

    标题中的“dm9161”指的是一种特定的硬件设备,可能是一个网络接口控制器或者通信芯片,而描述中提到的“dm9161的相关驱动基于Linux的”表明这个设备在Linux操作系统环境下需要特定的驱动程序来支持其正常工作。...

    大麦盒子DM1001、DM1004降级图文教程

    【2014.11.28】更新大麦盒子DM1001、DM1004降级图文教程

Global site tag (gtag.js) - Google Analytics