先吐槽下,这个问题不是什么大问题但是却找问题找了很久,很烦
先说说问题的场景吧,Spark加载Hive数据进行分析统计,然后写入Mysql数据库
之前是没有问题的,但是在添加了两个分析维度后突然就不行了。出现了下面的异常
Deadlock found when trying to get lock; try restarting transaction
语法是使用的 Replace INTO 语法
表死锁这让我很困扰!!**
先说下造成死锁的原因:
原因是Mysql表中的索引字段在Hive表中数据有重复所以造成了死锁!
为什么索引字段数据重复会造成死锁呢?
我这里简单的表达一下我个人的理解
首先介绍一下 Replace INTO 这个语法的执行过程和原理
Replace INTO 插入数据前会根据Mysql表中的索引字段,去查询有没有和你插入数据的索引字段有重复,
如果有就先将该数据删除在插入新数据。
再删除和插入的过程中就涉及到了一个行级锁问题,这个过程是有事物存在的,
也就是说要么成功更新数据,要么老数据不变,不能发生老的数据删除但是新的数据未插入这种现象
在删除数据之前首先获得这一行数据的锁,然后在做删除和插入的操作,直到操作结束释放该锁
下面说下我的具体原因
Spark写Mysql的任务是并发执行,多个节点或多个线程同时执行
应为Hive中的数据有重复,也就意味着索引建的值也会有重复,这些重复的数据可能在一个分区,
也可能不在一个分区。在结果集并发写入Mysql时就会出现死锁问题,
举例说明:
结果集中有两行索引 值一样的数据
在并发插入时第一行数据获得了索引 值的行级锁,执行事务操作
那么第二行也在插入,由于第一行获得了这个行级锁,第二行获取不到这个锁
自然在第二行插入时就会抛出异常
这种也叫资源抢占吧
我的解决办法就是,去除Hive数据中的重复数据,即可解决问题
解决办法还是要看公司的业务