MySQL迁移OceanBase问题记录
Mysql SQLNonTransientConnectionException 异常处理;数据库针对慢SQL或者未提交的事务,Oracle、MySQL、OceanBase选择了不同的策略去处理。OceanBase是分布式数据库,业务场景并发压力可能非常大,所以OceanBase选择了超时释放资源的策略。应用从Oracle或MySQL迁移到OceanBase时,需要根据业务需求动态调整上面所说的参
Maven 依赖调整
1. mysql 驱动:OceanBase 官方 推荐使用5.1.47版本
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>5.1.47</version>
</dependency>
2. druid 连接池:1.1.21后新版本DbType增加jdbc:oceanbase 类型,同时修复mybatisplus 3.2 LocalDateTime类型不兼容问题
Release Druid发布1.1.21版本,修复mybatisplus 3.2 LocalDateTime类型不兼容问题 · alibaba/druid · GitHub
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
3. Flyway: flyway不支持OceanBase,取消依赖
https://en.wikipedia.org/wiki/Flyway_(software)
<!-- flyway 官网 Supported Databases不包含oceanbase
<dependency>-->
<!-- <groupId>org.flywaydb</groupId>-->
<!-- <artifactId>flyway-core</artifactId>-->
<!-- </dependency>-->
4. 引入本地 oceanbase-client
<dependency>
<groupId>com.oceanbase</groupId>
<artifactId>oceanbase-client</artifactId>
<version>2.2.5</version>
<scope>system</scope>
<!-- <systemPath>${project.basedir}/lib/oceanbase-client-2.2.5.jar</systemPath> -->
<systemPath>${project.basedir}/lib/oceanbase-client-2.2.10.1jar</systemPath>
</dependency>
5.mybatis-plus 分页插件 3.4.0才支持oceanbase
Release v3.4.0 · baomidou/mybatis-plus · GitHub
<!--mybatis plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<!--mybatis plus 代码生成器 -->
<!--mybatis-plus 分页插件 3.4.0才支持oceanbase
com.baomidou.mybatisplus.annotation.DbType GitHub 提交记录-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
<scope>provided</scope>
</dependency>
6.升级druid和mybatis-plus版本之后导致druid和Localdatetime不兼容。在prepareStatement时会将Localdatetime类型的参数丢失
<!-- druid和localdatetime不兼容的问题-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-typehandlers-jsr310</artifactId>
<version>1.0.2</version>
</dependency>
MySQL、Oracle、OceanBase 参数配置差异
Oracle
Oracle数据库中,SQL语句的执行时间没有上限。如果SQL长时间执行而没有返回结果,Oracle不会干预,该SQL将一直运行,连接也会保持。如果SQL持有锁,锁和事务都将一直持续。SQL执行慢的原因通常有两类:
一是SQL性能问题,可能是因为需要扫描大量数据或进行大型数据集之间的连接,常见于数据仓库业务中;
二是SQL被其他会话阻塞,例如SQL在申请记录锁时,与其他会话发生锁冲突。
Oracle的策略是将处理慢SQL或阻塞问题的责任交给应用开发者。通常,这些问题由运维人员来解决,例如,通过脚本定时查询长时间运行的SQL(使用v$session_longops
视图)或检测长时间被阻塞的会话,然后通过kill session
命令终止这些会话。业务研发人员对此策略意见不一。部分数据库连接驱动提供了查询超时功能,可能在检测到SQL长时间未返回时,自动执行kill session
。
MySQL
MySQL中,慢SQL的处理更灵活。MySQL提供了设置SQL执行时间的超时参数。超时达到阈值时,SQL会提前返回或报错。在MySQL 5.6版本中,该参数为max_statement_time
(单位:毫秒),在5.7及之后版本为max_execution_time
(单位:毫秒)。默认值为0,表示永不超时。
相比之下,MySQL对慢SQL提供了更多主动控制的选项,而Oracle的策略更依赖应用和运维人员进行处理。
MySQL(特别是InnoDB引擎中),针对DML操作在申请锁被阻塞时,MySQL有一个参数用于设置锁等待的超时时间,称为innodb_lock_wait_timeout
(默认:50秒)。如果SQL在等待锁时超过了这个超时时间,MySQL会报错:"Lock wait timeout exceeded; try restarting transaction"。这表明锁等待超时,但不会自动回滚当前事务。应用程序需要捕获这个异常,并根据需要主动决定是回滚还是继续处理。
事务在锁等待超时时是否自动回滚取决于innodb_rollback_on_timeout
参数的设置,默认情况下是OFF
,意味着即使发生锁等待超时,事务也不会自动回滚。因此,应用程序需要谨慎处理这些错误,确保数据完整性,并决定是重新尝试事务、回滚还是采取其他措施。
Mysql SQLNonTransientConnectionException 异常处理
innodb_lock_wait_timeout , 默认值为 50秒 , 数据库锁超过这个时间,导致报错。
OceanBase
OceanBase对慢SQL处理只有一种策略。即针对每个SQL的执行时间设置一个超时阈值。参数是ob_query_timeout,默认值是10000000(微秒us),即10秒。这个默认时间很短,所以在OB里跑慢SQL很容易就碰到这个报错(-4012:Timeout)。这个参数是个租户(实例)变量,需要运维手动修改一下。
show session variables like 'ob_%timeout%';
+---------------------+-----------+
| Variable_name | Value |
+---------------------+-----------+
| ob_query_timeout | 10000000 |
| ob_trx_idle_timeout | 120000000 |
| ob_trx_timeout | 100000000 |
+---------------------+-----------+
set session ob_query_timeout=7000000;
set global ob_query_timeout=100000000;
注意,如果是修改租户(实例)变量的范围是全局(global),则需要会话重新连接才会生效。这个机制是跟MySQL保持一致的。也可以在会话层面修改。
OceanBase比MySQL做得更进一步的是针对未提交事务也增加了两个超时限制。一个是事务闲置超时时间,变量ob_trx_idle_timeout控制,默认值是120000000(微秒us),即120秒。第二个是事务提交超时时间,变量ob_trx_timeout控制,默认值是100000000(微秒us),即100秒。
OceanBase之所以在SQL执行和事务提交时设置超时时间,是为了避免慢SQL或阻塞的事务长时间占用数据库资源(如连接、内存等)。在高并发的互联网业务中,慢SQL或未提交的事务可能对数据库造成极大的压力。因此,即使因为超时而报错,这种策略也是明智的。
当业务系统频繁收到超时报错时,可能意味着应用设计存在问题,需要进行分析和优化。如果确实发现设计缺陷,应与运维团队协商,调整租户(实例)的全局超时设置。但如果全局设置的更改会影响所有连接,则可以考虑在会话级别调整超时值。例如,在批量处理逻辑中,事务可能需要较长时间运行,这时可以通过会话级别的配置来确保不受全局设置的限制。
OceanBase常见超时参数
OceanBase 租户在刚开始使用的时候,建议调大租户的几个超时参数。
1.ob_query_timeout:语句执行超时时间,单位 us, 默认值是 10000000 (也就是 10 秒)。 建议根据业务 SQL 平均执行时间水平调整。OLTP 场景调整短一些,OLAP 场景调整大一些。 初学者建议调大 10倍;
2.ob_trx_idle_timeout :事务空闲超时时间,单位 us, 默认值是 120000000(也就是 120 秒)。建议根据业务事务平均空闲时间水平调整。空闲事务会占用连接、可能持有锁不释放, 导致高并发时阻塞和死锁概率增加。不建议调大;
3.ob_trx_timeout :事务未提交超时时间,单位 us,默认值是 100000000 (也就是 100 秒)。 建议根据业务事务平均持续时间水平调整。事务长期不提交,会占用连接、可能持有锁不释 放,导致高并发时阻塞和死锁概率增加。不建议调大。如果是后台跑批业务,建议在会话级 别调大;
4.ob_trx_lock_timeout:事务申请加锁等待超时时间,单位 us,默认值是 -1(也就是不控制。 超时依然会受;
5.ob_query_timeout 限制。当调大了语句超时时间变量(ob_query_timeout)后,可以将 这个锁等待超时改为 10000000(即 10s)。减少阻塞和死锁的概率。
数据库针对慢SQL或者未提交的事务,Oracle、MySQL、OceanBase选择了不同的策略去处理。OceanBase是分布式数据库,业务场景并发压力可能非常大,所以OceanBase选择了超时释放资源的策略。应用从Oracle或MySQL迁移到OceanBase时,需要根据业务需求动态调整上面所说的参数配置。
数据迁移
使用 DataX 迁移 MySQL 表数据到 OceanBase 数据库,见OceanBase 官网:OceanBase分布式数据库-海量数据 笔笔算数
更多推荐
所有评论(0)