apache / incubator-seata

:fire: Seata is an easy-to-use, high-performance, open source distributed transaction solution.
https://seata.apache.org/
Apache License 2.0
25.22k stars 8.76k forks source link

AT模式下使用mysql的YEAR类型,在二阶段执行回滚更新数据库时出错 #4442

Open renliangyu857 opened 2 years ago

renliangyu857 commented 2 years ago

Ⅰ. Issue Description

针对issue#4402 对AT模式下的mysql type做了一轮测试 https://github.com/seata/seata/pull/4402,发现问题。 1)构造前置镜像时,对于YEAR类型,jdbc会将其自动转为DATE类型;在二阶段回滚时按照date类型更新数据时会报data truncated错误。应该是jdbc的bug。参考:https://github.com/jOOQ/jOOQ/issues/9738;https://bugs.mysql.com/bug.php?id=95045

Ⅱ. Describe what happened

image

Ⅲ. Describe what you expected to happen

Ⅳ. How to reproduce it (as minimally and precisely as possible)

在Mysql5及Mysql8下都可以复现该问题,可以使用https://github.com/seata/seata/pull/4402中的测试用例进行测试

Ⅴ. Anything else we need to know?

Ⅵ. Environment:

GoodBoyCoder commented 2 years ago

这个情况本质上是由于MySQL的JDBC驱动对Year类型字段与Date类型字段不做区分,无论是返回的字段类型值还是实际的数据类型都与Date保持一致,导致后续在setValue时无法区分出Date与Year而错误的设置了类型 image image 若要在驱动之上来解决,可以是在缓存的字段元数据修改Year字段的字段类型,同时在TableRecords#buildRecords对相应的Date类型做转换,但是可能存在误判风险影响较大。 目前建议使用Date或者是与int/smallint作为类型替代方案