zoukankan      html  css  js  c++  java
  • mysql主从与mycat与MHA

    主从同步

    本博客已迁移至www.lylblog.com,最新博文请访问新站点,欢迎各位来访。

    原理

    Master,记录数据更改操作

    启用binlog日志

    设置binlog日志格式

    设置server_id

    Slave运行两个线程

    Slave_IO      

    //复制master主机binlog日志文件里的sql到本机的relay-log文建立

    Slave_SQL   

    //执行本机relay-log文件里的sql语句,重现Master的数据操作

    配置主从同步

    确保从库上必须有主库上的数据

    配置主服务器

    reset master;                           //重置binlog日志

    vim /etc/my.cnf

    [mysqld]

    .. ..

    log_bin=dbsvr1-bin          //启用binlog日志

    server_id=10                            //指定服务器ID号(不可和从服务器重复)

    binlog_format=mixed      //指定日志格式

    systemctl restart mysqld

    mysql> grant replication slave on *.* to '用户名'@'从服务器ip' identified by '密码';

    //授权备份用户

    mysql>show master status\G;             //查看master状态

    .. ..

    File: dbsvr1-bin.000004                        //日志文件名

    Position: 334                                                //偏移位置

    Binlog_Do_DB:

    Binlog_Ignore_DB:

    Execute

    .. ..

    配置从服务器

    vim /etc/my.cnf

    [mysqld]

    .. ..

    server_id=20                            //指定服务器ID号(不可和主服务器重复)

    //以下为可选项

    og_bin=dbsvr2-bin           //启用binlog日志

    sync-binlog=1                   //允许日志同步

    read_only=1                     //只读模式,同步及SUPER权限用户例外

    systemctl restart mysqld

    mysql>change master to master_host='主服务器ip',

    -> master_user='用户名',

    -> master_password='123456',

    -> master_log_file='dbsvr1-bin.000004',     //监控的日志文件

    -> master_log_pos=334;                              //主服务器上的偏移位置

    mysql>change master to master_host='主服务器ip', \

    master_user='用户名’, \

    master_password='123456', \

    master_log_file='dbsvr1-bin.000004', \

    master_log_pos=334;

    mysql>change master to master_host='192.168.4.51', \

    master_user='repluser', \

    master_password='123456', \

    master_log_file='master51.000005', \

    master_log_pos=154;

    mysql> start slave;                                              //启动复制

    //以上信息会自动保存到/var/lib/mysql/master.info中,以后在change更改master信息时,需要先stop slave

    查看slave状态

    show slave status\G;

    Slave_IO_State: Waiting for master to send event

    Master_Host: 192.168.4.10

    Master_User: replicater

    .. ..

    Slave_IO_Running:Yes            //IO线程已运行

    Slave_SQL_Running:Yes          //SQL线程已运行

    //确保这两个选项为YES

    相关文件

    master.info                              //连接主服务器信息

    relay-log,info                                  //中继日志信息

    主机名-relay-bin.xxxxx           //中继日志

    主机名-relay-bin.index           //中继日志索引文件

    主服务器mysql配置选项

    针对所有从服务器生效

    vim /etc/my.cnf

    binlog_do_db=数据库名                     

    //配置记录哪些库的binlog日志(哪些库可以同步)

    binlog_ignore_db=数据库名               

    //配置不记录哪些库的binlog日志(不同步哪些库)

    从服务器mysql配置选项

    只针对当前服务器生效

    vim /etc/my.cnf

    log_slave_updates                        

    //级联更新,默认情况下主从从结构不会级联更新

    relay_log=dbsvr2-relay-bin            //指定中继日志文件名

    replicate_do_db=库名                  

    //仅复制指定库,其他库被忽略,此选项可设置多条

    replicate_ignore_db=库名            //不复制哪些库,和do_db不可共存

    复制模式

    异步复制    

    //主库在执行完客户端提交的事务后立即将结果返给客户端,并不关心从库是否已经接收并处理

    同步模式    

    //当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端

    半同步模式

    //主库在执行完客户端提交的事务后不会立即返回给客户端,而是等待至少一个从库接收并写到relay log中猜返回给客户端

    show variables like "have_dynamic_loading";

    //查看是否允许动态加载模块,默认允许

    命令行加载插件,用户需具有super权限

    临时设置,重启失效

    主库

    mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';

    从库

    mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';

    查看

    mysql> select plugin_name,plugin_status from information_schema.plugins where plugin_name like '%semi%';

    安装完插件后半同步默认时关闭的

    主库

    mysql> set global rpl_semi_sync_master_enable=1;

    从库

    mysql> set global rpl_semi_sync_slave_enabled=1;

    查看

    mysql> show variables lik "rpl_semi_sync_%_enabled";

    永久启用半同步复制

    vim /etc/my.cnf

    [mysqld]

    .. ..

    主库

    plugin-load=rpl_semi_sync_master=semisync_master.so

    rpl_semi_sync_master_enabled=1

    从库

    plugin-load=rpl_semi_sync_slave=semisync_slave.so

    rpl_semi_sync_slave_enabled=1

    systemctl restart mysqld

    mysql读写分离

    多台MySQL服务器分别提供读、写服务,均衡流量,通过主从复制保持数据一致性.由MySQL代理面向客户端

    收到SQL写请求时,交给服务器A处理,收到SQL读请求时,交给服务器B处理,具体区分策略由服务设置

    结构

    至少一组主从服务器,一台代理服务器访问mysql数据库

    安装maxscale

    rpm -ivh maxscale-2.1.2-1.rhel.7.x86_64.rpm

    修改配置文件

    vim /etc/maxscale.cnf

    [server1]            //定义数据库服务器主机名,有几个主机写几个server

    type=server

    address=192.168.4.10            //master主机ip地址

    port=3306

    protocol=MySQLBackend

    [server2]                                        //定义数据库服务器

    type=server

    address=192.168.4.20            //slave主机ip地址

    port=3306

    protocol=MySQLBackend

    [MySQL Monitor]                    //定义要监视的数据库服务器,监控插件

    type=monitor

    module=mysqlmon

    servers=server1, server2 

    //定义的主从数据库服务器主机名(逗号后面要有空格)

    user=scalemon                       //用户名

    passwd=111111                      //密码

    monitor_interval=10000

    将[Read-Only]注释

    [Read-Write Service]              //定义实现读写分离的数据库服务器,路由插件

    type=service

    router=readwritesplit

    servers=server1, server2

    //定义的主从数据库服务器主机名(逗号后面要有空格)

    user=maxscale                        //用户名

    passwd=111111                      //密码

    max_slave_connections=100%

    [Read-Write Listener]             //监听读写

    type=listener

    service=Read-Write Service

    protocol=MySQLClient

    port=4006

    [MaxAdmin Listener]

    type=listener

    service=MaxAdmin Service

    protocol=maxscaled

    socket=default

    port=4099

    //路由插件决定如何把客户端的请求转发给后端数据库服务器,读写分离和负载均衡的功能就是由这个模块实现的

    //监控插件对各个数据库服务器进行监控,例如发现某个数据库服务器响应很慢,那么就不向其转发请求了

    在主从服务器上授权用户

    mysql> grant replication slave, replication client on *.* to scalemon@'%' identified by “111111”;

    //创建监控用户

    mysql> grant select on mysql.* to maxscale@'%' identified by “111111”;

    //创建路由用户

    mysql> grant all on *.* to student@'%' identified by “111111”;

    //创建访问数据用户

    //授权的时候地址要么是%要么是绝对IP地址,网段范围无法识别,无法授权

    启动 maxscale

    maxscale --config=/etc/maxscale.cnf

    netstat -utnalp | grep maxscale

    tcp 0 0 192.168.1.110:58960 192.168.1.101:3306

    ESTABLISHED 19081/maxscale

    tcp 0 0 192.168.1.110:43508 192.168.1.111:3306

    ESTABLISHED 19081/maxscale

    tcp6 0 0 :::4006 :::* LISTEN 19081/maxscale

    //查看端口

    mysql -h代理服务器ip -P4006 -ustudent -p111111

    mysql>select @@hostname;                //查看当前访问的主机名

    mysql调优

    调优所有参数单位为毫秒

    提高MySQ 系统的性能,响应速度

    替换有问题的硬件(CPU/磁盘/内存等)

    服务程序的运行参数调整

    对 SQL 查询进行优化

    并发及连接控制

    max_connections             //允许的最大并发连接数

    connect_timeout             //等待建立连接的超时秒数,默认10秒,只在登录时有效

    wait_timeout                   //等待关闭连接的不活动超时秒数,默28800秒(8小时)

    show variables like "%关键字%"\G;           //查看sql系统变量

    show global status lik "max_used_connections";

    //查看当前已使用的连接数

    show variables like "max_connections";

    //查看默认最大连接数,使用的最大连接数要<=最大连接数的85%为理想比例

    缓存参数控制

    key_buffer-size                        //用于MyISAM引擎的关键索引缓存大小

    sort_buffer_size                      //为每个要排序的线程分配此大小的缓存空间

    read_buffer_size                            //为顺序读取表记录保留的缓存大小

    thread_cache_size                  //允许保存在缓存中被重用的线程数量

    table_open_cache                  //为所有线程缓存的打开的表的数量

    key_buffer-size指定索引缓冲区的大小,只对MyISAM表起作用,它决定索引处理的速度

    Key_reads和Key_read_requests做比例计算,数值较低时,可加大此缓存值

    sort_buffer_size增大此值可提高order by和group by的速度

    read_buffer_size此缓存值影响SQL查询的相应速度

    thread_cache_size当客户端断开之后,服务器处理此客户的线程将会缓存起来以响应下一个客户而不是销毁(前提是缓存数未达上限)

    即可以重新利用保存在缓存中线程的数量,当断开连接时如果缓存中还有空间,那么客户端的线程将被放到缓存中,如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,那么这个线程将被重新创建,如果有很多新的线程,增加这个值可以改善系统性能

    table_open_cache如果opend_tables大于此值,会拉低性能,将此值设置成max_connections的数

    优化SQL查询

    vim /etc/my.cnf

    [mysqld]

    .. ..

    slow_query_log=1                                        //启用慢查询

    slow_query_log_file=mysql-slow.log   //指定慢查询日志文件

    long_query_time=5                                      //超过此秒数的查询才会被记录

    log_queries_not_using_indexes=1             //记录没有使用索引查询语句

    mysqldumpslow /var/lib/mysql/mysql-slow.log

    //查看慢查询日志

    show variables like 'query_cache%';

    //查看查询缓存大小

    show variables like 'qcache%';

    //查看查询缓存统计

    调优思路总结

    升级硬件                                 //CPU 内存硬盘

    加大网络带宽                         //付费加大带宽

    调整mysql服务运行参数     //并发连接数,连接超时时间,重复使用的,线程数...

    调整与查询相关的参数         //查询缓存,索引缓存...

    启用慢查询日志                     //slow-query-log

    网络架构不合理                     //调整网络架构

    Mycat

    基于Java的分布式数据库系统中间层

    提供JDBC的链接方式,支持MySQL,Orale,SqlServer,Mongodb等,支持读写分离和高可用,实现数据分片

    基于阿里巴巴Cobar进行研发的开源软件,适用于数据大量写入的需求

    Mycat提供10中分片规则

    sharding-by-intfile                  //枚举法

    rule1                                               //固定分片

    auto-sharding-long                 //范围约定

    mod-long                                        //求模法     

    sharding-by-date                            //日期列分区法

    sharding-by-pattern                //通配取模

    sharding-by-prefixpattern             //ASCII码求模通配

    sharding-by-substring             //编程指定

    sharding-by-stringhash           //字符串拆分hash解析

    sharding-by-murmur               //一致性hash

    Mycat工作原理

    当Mycat收到一个SQL时,会先解析这个SQL涉及到的表,然后看此表的定义,如果有分片规则,则获取到SQL里分片字段的值,并匹配分片函数,得到SQL对应的分片列表.然后将SQL发往这些分片去执行,最后收集和处理所有分片返回的数据,输出到客户端

    Mycat部署

    拓扑结构

    拓扑名称

    主机名

    角色

    数据库名

    IP

    hostA

    client

    客户端

    192.168.4.254/24

    hostB

    Mycat

    Mycat服务器

    192.168.4.56/24

    hostC

    c1

    数据库服务器

    db1

    192.168.4.55/24

    hostD

    c2

    数据库服务器

    db2

    192.168.4.54/24

    1.装包

    1.1安装JDK

    因为Mycat是基于java开发的,所以需要安装JDK

    rpm -qa | grep -i jdk                            //检查是否已经安装JDK

    java-1.8.0-openjdk-1.8.0.65-3.b17.el7.x86_64

    java-1.8.0-openjdk-headless-1.8.0.65-3.b17.el7.x86_64

    1.2安装Mycat服务软件包

    tar -zxf Mycat-server-1.4-beta-20150604171601-linux.tar.gz

    //免安装,解压即可用

    mv mycat/ /usr/local/

    2.修改配置文件

    2.1目录结构说明

    bin                //包含Mycat命令

    catlet            //扩展功能

    conf              //配置文件

    lib                 //Mycat使用的jar包

    log                //启动日志和运行日志

    其中包含

    wrapper.log //启动日志,启动有问题看这个log

    mycat.log            //记录sql脚本执行后的具体报错内容

    2.2重要配置文件说明

    server.xml    //设置链接Mycat服务的账号,密码

    schema.xml //配置Mycat使用的真实数据库和表

    rule.xml        //定义Mycat分片规则

    2.3配置标签说明

    <user>...</user>

    //定义链接Mycat服务时使用的用户名密码及逻辑库名字

    <datanode>...</datanode>

    //指定数据节点,物理库的主机名和存储分片数据和数据库名

    <datahost>...</datahost>

    //指定数据库服务器的IP地址以及连接数据库使用的授权用户及密码

    3.修改配置文件

    3.1配置账号密码

    vim /usr/local/mycat/conf/server.xml

    <user name="test"> 

    //链接mycat服务时使用的用户名cat

    <property name="password">test</property>

    //使用test链接mycat的密码

    <property name="schemas">TESTDB</property>  

    //都好分离多个逻辑库

    <property name="readOnly">true</property>

    //开启只读权限

    </user>

    3.2定义分片信息

    <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">

    //逻辑库名,要和server.xml中定义的一致

    <table name="travelrecord" dataNode="dn1,dn2" rule="auto-sharding-long" />

    //定义分片的表

          

           <table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2" />

                <table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2" />

                <table name="hotnews" primaryKey="ID" dataNode="dn1,dn2" rule="mod-long"/>

                <table name="employee" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile" />

                <table name="customer" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile" />

    </schema>

    <dataNode Name="dn1" dataHost="c1" database="db1" />

    //定义分片使用的库,所在的物理主机,真正存储数据库的db1库在物理机c1上

    <dataNode Name="dn2" dataHost="c2" database="db2" />

    //指定c1名称主机对应的ip地址

    <dataHost name="c1" mxCon="1000" minCon="10" balance="0" writeYtpe="0" dbType="mysql" dbDriver="native">

                <heartbeat>select user()</heartbeat>

                <writeHost host="hostM1" url="192.168.4.55:3306" user="admin" password="123456">

           //访问数据库时,mycat链接数据库使用的用户名和密码

                </writeHost>

    </dataHost>

    //指定c2名称主机对应的ip地址

    <dataHost name="c2" mxCon="1000" minCon="10" balance="0" writeYtpe="0" dbType="mysql" dbDriver="native">

                <heartbeat>select user()</heartbeat>

                <writeHost host="hostM2" url="192.168.4.54:3306" user="admin" password="123456">

           //访问数据库时,mycat链接数据库使用的用户名和密码

                </writeHost>

    </dataHost>

    3.3修改数据库配置信息(所有主机)

    vim /etc/my.cnf

    [mysqld]

    .. ..

    lower_case_table_name=1   

    //表名区分大小写字母

    //重启mysqld

    systemctl restart mysqld

    //授权mycat链接数据库的用户

    MySQL> grant all on *.* to admin@"%" identified by "123456";

    4.启动服务

    vim /usr/local/mycat/conf/wrapper.conf

    # Java Application

    //第五行添加

    wrapper.java.command=java

    //查看java的安装目录

    which java

    /usr/bin/java

    //添加java的程序路径到PATH下

    echo "export PATH=/usr/local/mycat/bin" >> /etc/profile

    //查看mycat帮助

    mycat --help

    //启动mycat

    mycat start

    //检查mycat启动

    ss -anput | grep :8066

    5.在客户端链接mycat

    mysql -h Mycat服务器IP -P端口 -u用户名 -p密码

    mysql> show databases;

    MHA集群管理

    MySQL高可用环境下故障切换和主动提升的高可用软件

    在MySQL高可用方面是一个相对成熟的解决方案,比MySQL MMM更可靠

    MHA能在30秒内自动完成数据库的故障切换操作,切换过程中,也能最大程度上保证数据的一致性

    工作原理

    MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的 slave重新指向新的 master,整个故障转移过程对应用程序完全透明

    拓扑环境

    Master数据库服务器                   //192.168.4.51

    备用master数据库服务器          //192.168.4.52

    slave服务器                                   //192.168.4.53

    slave服务器                                   //192.168.4.54

    slave服务器                                   //192.168.4.55

    Mha_manager服务器                   //192.168.4.56

    VIP(Virtual IP)地址                  //192.168.4.100

    搭建流程

    1.搭建一主多从

    1.1主服务器(包含备用主服务器)

    vim /etc/my.cnf

    [mysqld]

    .. ..

    plugin-load =“rpl_semi_sync_master = semisync_master.so; rpl_semi_sync_slave = semisync_slave.so”

    rpl-semi-sync-master-enabled = 1

    rpl-semi-sync-slave-enabled = 1

    //开启半同步复制模式

    server_id=51

    //server_id不可和其他sql服务器重复

    log_bin=master52            //登录名

    binlog_format=mixed      //binlog日志格式

    mysql> set global relay_log_purge=off;

    //不自动删除本机的中继日志文件(所有节点)

    mysql> grant replication slave on *.* to repluser@"%" identified by"123456";

    //添加主从同步授权用户(所有节点)

    mysql> show master status;

    //查看master状态

    1.2备用服务器(包含备用主服务器)

    vim /etc/my.cnf

    [mysqld]

    .. ..

    server_id=52

    //server_id不可和其他sql服务器重复

    mysql> change master to master_host =“192.168.4.51”, \

    master_user =“repluser”, \

    master_password =“123456”, \

    master_log_file =“master51.000001”, \

    master_log_pos = 441;

    //根据实际情况创建从服务器

    //确保除主服务器外,其他服务器(包括备用主服务器)都是主服务器的从服务器

    //Slave_IO_Running和Slave_SQL_Running确保为YES

    1.3ssh root免密钥登录

    所有的主从服务器之间都需要设置ssh免密钥登录

    ssh keygen

    ssh-copy-ip root@192.168.4.51

    1.4安装依赖软件包

    1.4.1所有节点安装

    yum -y  install perl-DBD-mysql

    unzip mha-soft-student.zip

    cd mha-soft-student.zip

    rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm

    1.4.2管理机安装

    yum -y  install perl-ExtUtils-*   perl-CPAN-*

    tar -zxf mha4mysql-manager-0.56.tar.gz

    cd mha4mysql-manager-0.56

    perl Makefile.pl

    make

    make install

    1.5配置管理机环境

    1.5.1指定命令所在的路径

    cd mha4mysql-manager-0.56

    mkdir /root/bin

    cp bin/* /root/bin/

    //将MHA manager的命令放入$PATH路径的/root/bin下,方便使用

    1.5.2修改配置文件

    mkdir /etc/mha_manager/

    cd mha4mysql-manager-0.56/samples/conf/

    cp  app1.cnf   /etc/mha_manager/

    //将配置文件范例拷贝到配置目录

    cp /etc/mha_manager/app1.cnf /etc/mha_manager/app1.cnf.bak

    //备份

    vim  /etc/mha_manager/app1.cnf

    manager_workdir=/etc/mha_manager            

    //MHA manager配置文件目录

    manager_log=/etc/mha_manager/manager.log

    //日志目录

    master_ip_failover_script=/etc/mha_manager/master_ip_failover

    //主库地址更换脚本目录

    user=root

    password=123456

    //登录数据库用户名密码

    repl_user=repluser

    repl_password=123456

    //主从数据库设置的密码

    ssh_user=root

    ssh_port=22

    //ssh用户名密码

    //有几个数据库就写几个server

    [server1]

    hostname=192.168.4.51

    candidate_master=1        //主库

    [server2]

    candidate_master=1

    hostname=192.168.4.52

    [server3]

    hostname=192.168.4.53

    no_master=1                    //从库(不参与主库)

    1.5.3修改VIP文件(主库地址更换脚本)

    cd mha-soft-student

    cp master_ip_failover /etc/mha_manager/

    //将范本拷贝到配置目录

    //此范本为达内写好的范本,更改VIP地址后可以直接使用

    //此文件要有可执行权限

    cd mha4mysql-manager-0.56/samples/scripts

    cp master_ip_failover  /etc/mha_manager/

    //此范本为MHA自带范本,可用性未知

    //在35行添加(更改)

    my $vip = '192.168.4.100/24';  # Virtual IP

    my $key = "1";

    my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";

    my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";

    2.测试

    2.1测试配置文件

    vim /etc/mha_manager/app1.cnf

    #master_ip_failover_script=/etc/mha_manager/master_ip_failover

    //将主库地址更换脚本注释

    //测试会调用配置文件,此行不注释会将数据库的VIP地址更换

    2.2.1测试SSH联通性

    masterha_check_ssh  --conf=/etc/mha_manager/app1.cnf

    .... All SSH connection tests passed successfully.

    2.2.2测试主从库联通性

    masterha_check_repl --conf=/etc/mha_manager/app1.cnf

    .....MySQL Replication Health is OK.

    3.启动服务

    3.1启动配置文件

    vim /etc/mha_manager/app1.cnf

    master_ip_failover_script=/etc/mha_manager/master_ip_failover

    //取消注释

    3.2把VIP地址手动绑定到当前主库上

    ifconfig eth0:1 192.168.4.100/24

    ifconfig eth0:1

    //ifconfig eth0:1 down

    //VIP地址的作用,客户端访问只需访问VIP地址,而不需要管集群服务器的地址

    3.3启动服务

    masterha_manager --conf=/etc/mha_manager/app1.cnf --remove_dead_master_conf  --ignore_last_failover

    --remove_dead_master_conf

    //不在app1.cnf文件里删除宕机的主库的信息

    //主库down后,会将其的配置信息从配置文件中删除

    --ignore_last_failover

    //每次failover切换后会在管理目录生成文件app1.failover.complete,下次在切换的时候会发现有这个文件导致切换不成功,需要手动清理掉

    //ignore_last_failover忽略此文件

    masterha_check_status --conf=/etc/mha_manager/app1.cnf

    //manager端新开一个终端检查MHA的状态

    4.总结

    MHA集群中的所有主机必须是主库的从库(集群中不能有独立服务器)

    所有主机之间SSH要免密钥登录

    服务起来后,manager会监视主服务器的运行情况,当主服务器宕掉后(模拟停止mysql服务),manager会将VIP地址从宕机的主服务器上删除,并在备用主服务器上启用VIP地址,从服务器会自动选择备用的主服务器.配置文件中会删除宕机的配置,防止再宕机恢复之前备用主服务器再次宕机而导致服务器集群崩溃.

    宕机发生后,MHA manager会停止监控.

    主服务器恢复后,需要将主服务器的配置重新写入MHA配置文件中,主服务器要变成从服务器指向现在运行的备用主服务器,并重新启动manager监控

  • 相关阅读:
    DATAGUARD物理standby角色切换(笔记二)
    深入了解start with .....connect by (一)
    oracle lob字段处理
    InstallShield12命令行模式编译工程的几点问题总结Emma友情赞助转帖
    Installshield实用小函数为字符串截掉头尾空格
    使用Java Service Wrapper将Java程序发布成Windows Service艾泽拉斯之海洋女神出品
    Kevin专栏自定义安装对话框的界面
    Kevin专栏如何制作试用版安装包
    【海洋女神原创】关于installshield“完美卸载”的改进方法
    Installshield的相对路径问题
  • 原文地址:https://www.cnblogs.com/lylsr/p/10850066.html
Copyright © 2011-2022 走看看