临时表创建导致的问题及解决方案
起因
老系统用的ORM框架是hibernate5.2.2,开发发现一个诡异的BUG,一个批量的更新操作,竟然会影响到许多无关的数据,同时发现旧库中有个HT_*的表。
长话短说,有几张互相嵌套继承的表结构。如下图:
实体类似于这样:
问题分析
跟一波源码,其实就是为了解决这种变态的表结构的批量更新和删除,所应用的临时表处理方式。这个HT_*就是个临时表,当个过度作用罢了,是session作用域。正常一波操作
下,会清空drop掉这个表。但是现在完全没有drop,而且我们旧库中的这个HT表明显不是临时表,是个普通的实体表。所以问题就来了,没有清空,导致所有的更新都会走一遍这个实体HT表,所以问题就出现了。
问题解决
经过调查,这家伙为什么不用临时表,而自己蹩脚的搞个实体表,是因为mysql5.6,引入GTID全局事务机制,为了主备的一致性。所以不允许在事务里创建和删除临时表,所以没办法为了完成任务,在库里建了个实体表来应付过去。有点无语啊,这么一弄,所有的批量操作都会被这个HT实体表所影响。
问题找到了,如何解决这个问题,就很简单了,小升级下到hibernate5.2.8就提供了别的解决方案来替换掉这套临时表的方案。
<property name="hibernate.hql.bulk_id_strategy"
value="org.hibernate.hql.spi.id.inline.InlineIdsOrClauseBulkIdStrategy"
/>
多的就不想多写了,这套机制到底咋回事,可以参考:https://in.relation.to/2017/02/01/non-temporary-table-bulk-id-strategies/