GVKun编程网logo

阿里云rds数据库迁移实战(多数据源)(阿里云rds数据库导出)

5

如果您对阿里云rds数据库迁移实战感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于阿里云rds数据库迁移实战的详细内容,我们还将为您解答多数据源的相关问题,并且为您提供关于c

如果您对阿里云rds数据库迁移实战感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于阿里云rds数据库迁移实战的详细内容,我们还将为您解答多数据源的相关问题,并且为您提供关于codis/redis数据数据迁移至阿里云redis服务器、Java与阿里云RDS对接:如何实现高可用、可扩展的数据库服务?、mysql 通过拷贝数据文件的方式进行数据库迁移实例、Room数据库迁移实战的有价值信息。

本文目录一览:

阿里云rds数据库迁移实战(多数据源)(阿里云rds数据库导出)

阿里云rds数据库迁移实战(多数据源)(阿里云rds数据库导出)

  由于某几个业务表数据量太大,数据由业务写,数据部门读。

  写压力不大,读却很容易导致长时间等待问题(读由单独系统进行读),导致连接被占用,从而容易并发稍稍增长导致全库卡死!

  于是,就拆库呗。

  业务系统拆分就不要做了(微服务化),没那工夫。

  直接原系统拆两个数据源出来,对某几个高压力表的写就单独用这个数据源,从而减轻压力。

所以,分库工作就变为了两个步骤:

  1. 两个数据源读写业务;

  2. 将新数据库写动作同步回读库;

  再由于方便性,数据库也是使用阿里的rds数据库,一个变为两个!

  代码上做两个数据源很简单,尤其是在原有代码就写得比较清晰的情况下;

如下是使用springboot和mybatis做的多数据源配置:

  1. 配置多个数据源类;

  2. 启用mybatis多数据源,加载不同配置bean;

  3. 根据扫描路径区别使用的数据源;

  4. 根据扫描路径将需要拆分的表与原表区别;

  5. 测试时可使用同同机器上多库形式运行,上线后为多实例同库运行;

  6. 验证功能可用性;如有问题,及时修改;

  具体配置如下:

// 原数据源配置
@Configuration
@MapperScan(basePackages = MainDataSourceConfig.SCAN_BASE_PACKAGE, sqlSessionFactoryRef = "sqlSessionFactory")
public class MainDataSourceConfig {

    public static final String SCAN_BASE_PACKAGE = "com.xxx.dao.mapper.main";

    /**
     * xml 配置文件扫描路径
     */
    public static final String SCAN_XML_MAPPER_LOCATION = "classpath:mybatis/mappers/mysql/main/**/*Mapper.xml";

    //jdbcConfig
    @Value("${jdbc.main.url}")
    private String jdbcUrl;
    @Value("${jdbc.main.driver}")
    private String driverName;
    @Value("${pool.main.maxPoolSize}")
    private int maxPoolSize;
    @Value("${jdbc.main.username}")
    private String jdbcUserName;
    @Value("${jdbc.main.password}")
    private String jdbcPwd;
    @Value("${pool.main.maxWait}")
    private int jdbcMaxWait;
    @Value("${pool.main.validationQuery}")
    private String validationQuery;

    @Bean(name = "druidDataSource")
    @Primary
    public DruidDataSource druidDataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setUrl(jdbcUrl);
        ds.setDriverClassName(driverName);
        ds.setMaxActive(maxPoolSize);
        ds.setUsername(jdbcUserName);
        ds.setPassword(jdbcPwd);
        ds.setRemoveAbandoned(true);
        ds.setMaxWait(jdbcMaxWait);
        ds.setValidationQuery(validationQuery);
        return ds;
    }
    
    @Bean(name = "dataSourceTransactionManager")
    @Primary
    public DataSourceTransactionManager dataSourceTransactionManager(){
        DataSourceTransactionManager dm = new DataSourceTransactionManager();
        dm.setDataSource(druidDataSource());
        return dm;
    }

    @Bean(name="sqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] mapperXmlResource = resolver.getResources(SCAN_XML_MAPPER_LOCATION);
        sqlSessionFactory.setDataSource(druidDataSource());
        sqlSessionFactory.setMapperLocations(mapperXmlResource);
        return sqlSessionFactory.getObject();
    }
    
}

// 新数据源配置,仅仅改了下配置名,但是还不得不另一个配置类
@Configuration
@MapperScan(basePackages = ExtraDataSourceConfig.SCAN_BASE_PACKAGE, sqlSessionFactoryRef = "sqlSessionFactoryExt")
public class ExtraDataSourceConfig {

    public static final String SCAN_BASE_PACKAGE = "com.xxx.dao.mapper.ext";

    /**
     * xml 配置文件扫描路径
     */
    public static final String SCAN_XML_MAPPER_LOCATION = "classpath:mybatis/mappers/mysql/ext/**/*Mapper.xml";

    //jdbcConfig
    @Value("${jdbc.ext.url}")
    private String jdbcUrl;
    @Value("${jdbc.ext.driver}")
    private String driverName;
    @Value("${pool.ext.maxPoolSize}")
    private int maxPoolSize;
    @Value("${jdbc.ext.username}")
    private String jdbcUserName;
    @Value("${jdbc.ext.password}")
    private String jdbcPwd;
    @Value("${pool.ext.maxWait}")
    private int jdbcMaxWait;
    @Value("${pool.ext.validationQuery}")
    private String validationQuery;

    @Bean(name = "druidDataSourceExt")
    public DruidDataSource druidDataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setUrl(jdbcUrl);
        ds.setDriverClassName(driverName);
        ds.setMaxActive(maxPoolSize);
        ds.setUsername(jdbcUserName);
        ds.setPassword(jdbcPwd);
        ds.setRemoveAbandoned(true);
        ds.setMaxWait(jdbcMaxWait);
        ds.setValidationQuery(validationQuery);
        return ds;
    }
    
    @Bean(name = "dataSourceTransactionManagerExt")
    public DataSourceTransactionManager dataSourceTransactionManager(){
        DataSourceTransactionManager dm = new DataSourceTransactionManager();
        dm.setDataSource(druidDataSource());
        return dm;
    }

    @Bean(name="sqlSessionFactoryExt")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] mapperXmlResource = resolver.getResources(SCAN_XML_MAPPER_LOCATION);
        sqlSessionFactory.setDataSource(druidDataSource());
        sqlSessionFactory.setMapperLocations(mapperXmlResource);
        return sqlSessionFactory.getObject();
    }
    
}

  然后,将需要分离的表操作转移到相应的包路径下,即可实现多数据源操作了!

而多数据源配置对于基于xml配置spring来说,可能更加直观更加简单,甚至xml文件都不用分离!

<!-- 原数据源配置 -->
    <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="url" value="${jdbc.main.url}" />
        <property name="username" value="${jdbc.main.username}" />
        <property name="password" value="${jdbc.main.password}" />
        <property name="maxActive" value="${jdbc.main.maxActive}" />
        <property name="maxWait" value="${jdbc.main.maxWait}" />
    </bean>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:mybatis-config.xml" />
        <property name="mapperLocations">
            <list>
                <value>classpath:mybatis/mappers/mysql/main/**/*Mapper.xml</value>
            </list>
        </property>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager" /> 
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
      <property name="basePackage" value="com.xxx.dao.automapper.main" />
      <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>
    
    <!-- 第二个数据源的配置 -->
    <bean name="dataSourceExt" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="url" value="${jdbc.ext.url}" />
        <property name="username" value="${jdbc.ext.username}" />
        <property name="password" value="${jdbc.ext.password}" />
        <property name="maxActive" value="${jdbc.ext.maxActive}" />
        <property name="maxWait" value="${jdbc.ext.maxWait}" />
    </bean>
    <bean id="sqlSessionFactoryExt" class="org.mybatis.spring.SqlSessionFactoryBean">
      <property name="dataSource" ref="dataSourceExt" />
      <property name="configLocation" value="classpath:config/mybatis-config.xml" />
      <property name="mapperLocations">
          <list>
            <value>classpath:mybatis/mappers/mysql/ext/**/*Mapper.xml</value>
          </list>
      </property>
    </bean>
    <bean id="transactionManagerExt" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSourceExt" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManagerExt" /> 
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryExt"/>
        <property name="basePackage" value="com.xxx.dao.automapper.ext"/>
    </bean>

 

  所以,还是那句话:不是所有听起来好的东西就一定是好,在这里转换为不是所有听起来方便的东西用起来就一定方便!

 

代码ok后,还剩下一个问题:独立后的写动作同步问题!

  如果是自行搭建的mysql服务,我们很自然地考虑使用binlog同步(主从)来做!具体配置方法也不复杂,自行查找资料即可!

 

  如果使用阿里云服务,则不是binlog那样的配置了(但其实质仍然是对binlog的订阅写)。不过倒也都是页面操作!(网上不一定好找资料,但是官网上一定是最全的)

 

要进行数据库迁移,大体步骤分为:

  1. 先要将现有数据迁移到新实例上;

  2. 将部分新数据写入新实例(部分数据仍直接写现有实例,做到业务剥离的同时还可以减少数据同步的开销);

  3. 将新实例数据同步回原实例库;

 

DTS服务(数据传输服务),专门用于做数据迁移和数据同步!

  其打开方式为:

  1. 自然是花钱买服务了,买好后才能进入操作页面;这里服务要分两个:一是新实例rds数据库,二是新实例同步回原实例的同步服务;

  2. 设置ip白名单,以使mysql可访问;

  3. 创建高权限用户,如root,以使后续可高权限操作mysql,同步时可使用该账号或者另用一个普通读写账号;

  4. 将全量数据刷入新实例,这里可以选择阿里云免费的数据库迁移服务,也可以自己将数据dump下来,然后自行导致新库;(不过服务既然是免费的,那为啥不用呢!)

  5. 设置单向同步,从新实例到原实例,此时是不会有数据同步的,因为没有新写入;

  6. 数据刷入,同步设置完成后,就可以发布新代码了,此时最好将前端入口停止,否则可能出现数据错乱问题;

  7. 发布代码后,需要自行验证。此时,先选择一台机器进行验证,可以选择两种方式验证:一是自行调用关键接口进行验证;二是将该机器绑定eip外网,使用该外网进行页面访问验证(更完整的验证);验证的方向主要有两个:1. 接口正常响应,没有错误发生(此处应该要有监控设施,否则只能凭感觉);2. 数据有没有正常同步(一般同步都是秒级的);

  8. 将代码发布到集群中,观察各机器运行情况!此处主要查看数据库连接情况,是否存在连接失败情况,应用监控是主要手段,也可以通过mysql的show full processlist; 进行查看应用连接db情况;

  9. 观察正常后,此时可以将前端应用入口打开,此时如有条件,应限制ip访问,使变更进行充分测试无误;

  10. 一切无误后,完全开放访问服务;监控用户数据,迁移完成;

 

至此,整个迁移就完成了,其实思路是很简单的,关键是要小心操作。一个不小心的操作,就可能带来很大的隐患,毕竟,数据无小事!请保持对数据和代码的敬畏!

 

临了临了,附几个操作的贴心小技巧,避免入坑!

  1. 买rds数据库时,尽量买与原实例相同的区域(大区和可用区都相同),否则后期在做同步的时候会花更多的钱,因为跨区的网络通信会让你支付更多;

  2. 新实例数据库容量可以稍微降配以节省钱,因为毕竟你是将原来的部分功能拆分出来的,没必要一开始就为全部将来买单;

  3. 买同步服务时,注意几点:1. 按量计算(按小时)比预付费(包月)更贵,但是也更容易订制化,如果仅仅操作两个rds间同步,且短时间内不会下线服务,则建议选择预付费包月形式;2. 将区域选择正确,比如同区域同步将更便宜;3. 能单向同步就不要双向同步了,便宜的同时,也减小了误操作带来的影响;4. 同步性能一般小流量选择small即可,高配的同步用不上关键是贵;

  4. 同步服务尽早开启,但是后期对于账号密码的变更,一定要及时更改同步配置,否则将带来数据一致性问题;(人工发现往往较晚,尽量设置监控报警)

  5. 数据库白名单中,需要加入阿里云数据传输服务的白名单,否则无法检查数据库响应性及同步作业;

  6. 选择同步对象时,尽量以库作为单位!如果选择以表为同步单位,将存在后续新增表时,不会同步回原实例情况。如果实在不能以库作为单位,在后续迭代时,一定记得添加此处同步表;(关注点太多,麻烦)

  7. 后期做数据变更时,注意操作对象所属实例,别一顿操作猛如虎,然后没什么卵用,因为我们只是选择了单向同步;

  8. 自己可以不定期地做checksum检查,以确认同步功能正常工作;(checksum table test)

  9. 代码上分库一定要做准确了,因为这里可能是一定时间内的唯一可信参考资料;(简单但是关键)

 

最后,我还想说下使用别人服务和自己动手的一些个人感觉:

  1. 使用自己搭建的服务,最大的好处在于可以做任意的改变不受限,而且不需要付出额外的可见费用;

  2. 使用自己的服务的可能坏处是:如果你不是这方面的专家,往往会被自己埋下的各种坑难住;遇到问题没能力处理;考虑方面不周全,容易引发安全问题;对未来的因素没办法考虑,使后期运作困难;如果你是专家,那多半这些都不是事儿;

  3. 使用别人的服务,最大的好处就是简单易用,且有人维护;这些服务往往都是一路填坑过来的,时间越久往往越可靠(百年老字号最佳,哈哈);安全性、扩展性、性能调优、高可用等等;

  4. 使用别人的服务,其坏处主要是钱的问题,这个自不必说。还有个不是钱的问题的坏处,那就是你不能随意订制你想要的功能了,你的能力被别人限制住了,这个可能促使你转场到自己提供服务;另外,各家提供的服务都不一样,不像自己搭建的服务,网上会有各种资料可查,所以有一定的学习成本,具体取决于官方设计与官方文档的完整性(当然一般都会很简单);其实还有一个,就不说了,懂的都懂;

 

  好了,借着数据库迁移的小事,扯了这些淡。只当是抛砖引玉了!欢迎指教!

 

codis/redis数据数据迁移至阿里云redis服务器

codis/redis数据数据迁移至阿里云redis服务器

本次迁移采用了唯品会的开源工具RMT

1.阿里云redis服务器的购买

注:要和生产上数据的内存大小一致 不然有些key会迁移失败

很明显的OOM报错

2.迁移机器的cpu要足够  迁移会有一段时间的负载上升 对迁移机器的IOPS有要求

rmt_redis.c:1474 Error: I/O error reading bulk count from MASTER   

这种报错你就需要查看一下 迁移codis服务器的性能了

3.RMT(redis-migrate-tool)工具的安装

git clone https://github.com/vipshop/redis-migrate-tool.git

cd redis-migrate-tool

autoreconf -fvi  (没有的话yum一下)

./configure

make

4.RMT的配置

[source]
type: single
servers:
- codis:端口

[target]
type: single
servers:
 - ali.redis.rds.aliyuncs.com:端口
 redis_auth:密码
[common]
listen: 0.0.0.0:8888
mbuf_size: 1024

5.RMT启动

redis-migrate-tool -c rmt.conf -o rmt.log -d

6.RMT日志

出现如下说明 开始备份了

540350520268102-16856.rdb write complete

7.检查

通知状态页和 dbsize 确定 Key 数量是否一致 (初始同步完成) 执行 redis-cli -p 8888 info 确认

# 为 1
all_rdb_received:1 
all_rdb_parsed:1
# Codis group 数量 rdb_received_count:2 rdb_parsed_count:2 

配置服务连接 Redis 实例,检查 Codis 连接,知道所有连接断开,执行 redis-cli -p 8888 info 确认

# 为1
all_rdb_received:1 
all_rdb_parsed:1
# Codis group 数量 rdb_received_count:2 rdb_parsed_count:2 # 一致 total_msgs_recv:27005 total_msgs_sent:27005 # 为0 total_mbufs_inqueue:0 total_msgs_outqueue:0

 

 具体配置文件可以参考:https://blog.csdn.net/ahzxj2012/article/details/74347984

Java与阿里云RDS对接:如何实现高可用、可扩展的数据库服务?

Java与阿里云RDS对接:如何实现高可用、可扩展的数据库服务?

java与阿里云rds对接:如何实现高可用、可扩展的数据库服务?

引言:
现如今,随着互联网行业的快速发展,对于数据库服务的需求也越来越高。阿里云的RDS(Relational Database Service)作为云计算领域的重要产品,提供了一种高性能、高可用、可扩展的数据库解决方案。而Java作为互联网开发的常用语言,与RDS的对接也成为了众多开发人员关注的话题。本文将介绍如何使用Java与阿里云RDS对接,并实现高可用和可扩展的数据库服务。

一、RDS概述
阿里云RDS是一种托管式云数据库服务,它提供了许多数据库引擎的选择,包括MySQL、SQL Server、PostgreSQL、Redis等。RDS具备高可用、安全、易管理等特点,使得开发者无需关心底层数据库服务器的搭建、维护等问题,从而能够更好地专注于应用开发。

二、Java与RDS的对接
Java与RDS的对接主要通过数据库驱动来实现。对于MySQL数据库,我们可以使用JDBC驱动来连接RDS。以下是一个使用JDBC连接RDS的示例代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class RDSConnectionExample {
   public static void main(String[] args) {
      // RDS连接参数
      String url = "jdbc:mysql://rdsxxx.mysql.rds.aliyuncs.com:3306/testdb";
      String username = "root";
      String password = "yourpassword";
   
      // 加载数据库驱动
      try {
         Class.forName("com.mysql.cj.jdbc.Driver");
      } catch (ClassNotFoundException e) {
         e.printStackTrace();
      }
      
      // 建立数据库连接
      try (Connection conn = DriverManager.getConnection(url, username, password)) {
         Statement stmt = conn.createStatement();
         String sql = "SELECT * FROM user";
         ResultSet rs = stmt.executeQuery(sql);
         
         // 处理数据结果集
         while(rs.next()){
            int id  = rs.getInt("id");
            String name = rs.getString("name");
            int age = rs.getInt("age");
            
            System.out.println("id: " + id + ", name: " + name + ", age: " + age);
         }
      } catch (SQLException e) {
         e.printStackTrace();
      }
   }
}
登录后复制

以上代码中,我们使用了JDBC的DriverManager来加载MySQL的驱动,并创建了一个数据库连接。然后,创建了一个Statement对象来执行SQL查询语句,并最终通过ResultSet来获取查询结果。

立即学习“Java免费学习笔记(深入)”;

三、实现高可用的数据库服务
高可用是一个数据库服务必不可少的特性,它能够确保数据库在出现故障的情况下仍能够持续提供服务。阿里云RDS通过提供主备模式来实现高可用性。在主备模式下,主数据库负责处理读写操作,而备数据库则负责实时复制主数据库的数据。在主数据库发生故障时,备数据库会自动接管服务而成为新的主数据库。

对于Java应用程序来说,要实现高可用的数据库服务,可以使用RDS提供的读写分离功能。读写分离可以将读请求分发到备库,从而减轻主库的负载压力。以下是一个使用读写分离的示例代码:

import com.mysql.cj.jdbc.MysqlDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class RDSReadWriteSplitExample {
   public static void main(String[] args) {
      // RDS连接参数
      String url = "jdbc:mysql:loadbalance://rdsxxx.mysql.rds.aliyuncs.com:3306/testdb";
      String username = "root";
      String password = "yourpassword";

      // 创建读写分离数据源
      MysqlDataSource ds = new MysqlDataSource();
      ds.setURL(url);
      ds.setUser(username);
      ds.setPassword(password);
      ds.setReadOnlyPropagatesToServer(true);

      try (Connection conn = ds.getConnection()) {
         Statement stmt = conn.createStatement();
         String sql = "SELECT * FROM user";
         ResultSet rs = stmt.executeQuery(sql);

         // 处理数据结果集
         while (rs.next()) {
            int id = rs.getInt("id");
            String name = rs.getString("name");
            int age = rs.getInt("age");

            System.out.println("id: " + id + ", name: " + name + ", age: " + age);
         }
      } catch (SQLException e) {
         e.printStackTrace();
      }
   }
}
登录后复制

在以上代码中,我们引入了MysqlDataSource类,它是RDS提供的用于支持读写分离的数据源。通过设置URL参数中的loadbalance关键字,可以使连接在读操作时自动进行读写分离。这样,即使主库发生故障,读请求也能够被自动分发到备库上进行处理。

四、实现可扩展的数据库服务
当应用的访问量不断增加时,数据库的扩展性也变得非常重要。阿里云RDS通过提供扩容和分库分表来实现可扩展的数据库服务。

扩容是指增加数据库的计算和存储资源,以满足大规模访问的需求。在阿里云RDS中,我们可以通过控制台或API来进行扩容操作。只需简单设置CPU、内存、磁盘等参数,即可完成数据库的扩容。

分库分表是指将一个大型数据库拆分成多个小型数据库,每个数据库只负责处理部分数据。这样可以减轻单个数据节点的负载压力,提高数据库的性能和可扩展性。对于Java应用程序来说,可以使用Sharding-JDBC来实现分库分表的功能。

Sharding-JDBC是一个开源的Java数据库中间件,它可以将数据分片并存储在多个数据库中,同时提供透明的数据读写操作。以下是一个使用Sharding-JDBC的示例代码:

import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class RDSDataShardingExample {
   public static void main(String[] args) {
      // RDS连接参数
      String url = "jdbc:mysql://localhost:3306/shardingsphere_db";
      String username = "root";
      String password = "root";

      // 创建数据源配置
      Map<String, DataSource> dataSourceMap = new HashMap<>();
      dataSourceMap.put("ds0", createDataSource("ds0", url));
      dataSourceMap.put("ds1", createDataSource("ds1", url));

      // 创建ShardingSphere数据源
      DataSource dataSource;
      try {
         dataSource = ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, getProperties());
      } catch (SQLException e) {
         throw new RuntimeException("Create data source error", e);
      }

      try (Connection conn = dataSource.getConnection()) {
         Statement stmt = conn.createStatement();
         String sql = "SELECT * FROM user";
         ResultSet rs = stmt.executeQuery(sql);

         // 处理数据结果集
         while (rs.next()) {
            int id = rs.getInt("id");
            String name = rs.getString("name");
            int age = rs.getInt("age");

            System.out.println("id: " + id + ", name: " + name + ", age: " + age);
         }
      } catch (SQLException e) {
         e.printStackTrace();
      }
   }

   // 创建数据源
   private static DataSource createDataSource(String dataSourceName, String url) {
      MysqlDataSource ds = new MysqlDataSource();
      ds.setURL(url);
      ds.setUser(username);
      ds.setPassword(password);
      return ds;
   }

   // 获取ShardingSphere属性配置
   private static Properties getProperties(){
      Properties properties = new Properties();
      properties.setProperty("sql.show", Boolean.TRUE.toString());
      return properties;
   }
}
登录后复制

在以上代码中,我们使用了Sharding-JDBC提供的ShardingSphereDataSourceFactory来创建数据源,通过配置不同的数据源名称和URL,我们可以指定不同的数据库进行数据分片。这样,即使面对大规模的数据集,我们也可以通过分库分表的方式实现数据库的可扩展。

总结:
本文介绍了如何使用Java与阿里云RDS对接,并实现了高可用和可扩展的数据库服务。通过使用JDBC驱动,我们可以轻松实现与RDS的连接,并进行数据的读写操作。同时,通过读写分离和分库分表技术,我们可以增加数据库的可用性和扩展性。希望本文能够对开发人员在Java与RDS对接方面提供一些帮助和指导。

以上就是Java与阿里云RDS对接:如何实现高可用、可扩展的数据库服务?的详细内容,更多请关注php中文网其它相关文章!

mysql 通过拷贝数据文件的方式进行数据库迁移实例

mysql 通过拷贝数据文件的方式进行数据库迁移实例

MysqL通过拷贝数据文件的方式进行数据库迁移

--环境windows

将源机器A数据库拷贝到目标机器B:

我先在目标机器B上安装MysqL,停止MysqL服务,然后将源机器A的data下关于数据库的文件和ibdata1拷贝过去,其余不用拷贝。如图:

源机器A:

启动目标数据库服务net start MysqL,即可查看到导过来的所有数据库了。

注意:ibdata1一定不要忘记拷贝,且要拷贝到准确的位置(如我目标机器的ibdata1在E:\MysqL Datafiles,不在data路径下,我就先备份下它的ibdata1,再拷贝到E:\MysqL Datafiles)否则查询拷贝过去的表会报错:

MysqL> use platform;

Database changed

MysqL> show tables;

+-----------------------+

| Tables_in_platform  |

+-----------------------+

| mobile_scanner    |

| sharer        |

| sharer_mobile_scanner |

| statistics      |

| test         |

+-----------------------+

5 rows in set (0.02 sec) 

MysqL> desc test;

ERROR 1146 (42S02): Table 'platform.test'doesn't exist 

在Linux下也是类似的方式,但要注意拷贝完文件后,记得改下data文件夹owner为MysqL。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Room数据库迁移实战

Room数据库迁移实战

一,修改Entity类,升级database的version,添加Migration对象用于升级

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
  @Override
  public void migrate(@NonNull SupportSQLiteDatabase database) {
    database.execSQL("alter table MptModel add column isInternal INTEGER not null default 0");
    database.execSQL("alter table MptModel add column internalScopes TEXT");
    database.execSQL("delete from MptModel");
  }
};
ScopeAuthorizeDatabase database = Room
    .databaseBuilder(ContextUtils.getApplicationContext(),
        ScopeAuthorizeDatabase.class, dbPath)
    .addMigrations(MIGRATION_1_2)
    .build();

二,为确保迁移成功,必须要做单元测试

根据本人亲身体验,强烈建议编写单元测试
单元测试可以尽可能多地测试各种场景,而且及时反馈,不仅降低出bug的可能,还提升了开发效率。

1,导出架构,添加以下配置,在编译时room会导出数据库架构信息到json文件;
将架构信息位置添加为资源文件夹

// module的build.gradle
android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }
    sourceSets {
        androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
    }
}
dependencies {
    androidTestImplementation "androidx.room:room-testing:2.2.1"
}

2,编写单元测试
首先创建一个helper类
测试时先创建低版本的数据库,插入数据,关闭数据库。然后执行迁移命令,检查数据库数据是否正常

public class ScopeAuthorizeDatabaseTest {
  private static final String TEST_DB = "migration-scope-authorize-db-test";
  @Rule
  public MigrationTestHelper helper;
  public ScopeAuthorizeDatabaseTest() {
    helper = new MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
        ScopeAuthorizeDatabase.class.getCanonicalName(),
        new FrameworkSQLiteOpenHelperFactory());
  }
  @Test
  public void migrate1To2() throws IOException {
    SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 1);
    // db has schema version 1. insert some data using SQL queries.
    // You cannot use DAO classes because they expect the latest schema.
    db.execSQL(
        "insert into MptModel (miniAppId,miniAppMpt,openId) values (''ks001'',''hello'',''world'')");
    Cursor query1 = db.query("select * from MptModel");
    query1.moveToFirst();
    assertEquals(1, query1.getCount());
    assertEquals(3, query1.getColumnCount());
    // Prepare for the next version.
    db.close();
    // Re-open the database with version 2 and provide
    // MIGRATION_1_2 as the migration process.
    db = helper.runMigrationsAndValidate(TEST_DB, 2, true, MIGRATION_1_2);
    // MigrationTestHelper automatically verifies the schema changes,
    // but you need to validate that the data was migrated properly.
    Cursor query2 = db.query("select * from MptModel");
    query2.moveToFirst();
    assertEquals(0, query2.getCount());// 升级策略是丢弃旧数据
    assertEquals(5, query2.getColumnCount());
    // 插入新数据
    db.execSQL(
        "insert into MptModel (miniAppId,miniAppMpt,openId) values (''ks001'',''hello'',''world'')");
    Cursor query3 = db.query("select * from MptModel");
    assertEquals(1, query3.getCount());
    query3.moveToFirst();
    // 验证column
    String miniAppId = query3.getString(query3.getColumnIndex("miniAppId"));
    String miniAppMpt = query3.getString(query3.getColumnIndex("miniAppMpt"));
    String openId = query3.getString(query3.getColumnIndex("openId"));
    int isInternal = query3.getInt(query3.getColumnIndex("isInternal"));
    String internalScopes = query3.getString(query3.getColumnIndex("internalScopes"));
    assertEquals("ks001", miniAppId);
    assertEquals("hello", miniAppMpt);
    assertEquals("world", openId);
    assertEquals(0, isInternal);// 默认为false
    assertNull(internalScopes);// 默认为null
  }
}

三,兜底策略
有时候可能缺失了部分升级路径,这时会发生IllegalStateException,为防止这种情况,需要使用兜底策略。

ScopeAuthorizeDatabase database = Room
    .databaseBuilder(ContextUtils.getApplicationContext(),
        ScopeAuthorizeDatabase.class, dbPath)
    .addMigrations(MIGRATION_1_2)
    .fallbackToDestructiveMigration()
    .build();

今天关于阿里云rds数据库迁移实战多数据源的讲解已经结束,谢谢您的阅读,如果想了解更多关于codis/redis数据数据迁移至阿里云redis服务器、Java与阿里云RDS对接:如何实现高可用、可扩展的数据库服务?、mysql 通过拷贝数据文件的方式进行数据库迁移实例、Room数据库迁移实战的相关知识,请在本站搜索。

本文标签: