spark遇到的死鎖

數據庫基礎知識: http://blog.csdn.net/luyaran/article/details/53502917

 

死鎖:如果需要“修改”一條數據,首先數據庫管理系統會在上面加鎖,以保證在同一時間只有一個事務能進行修改操作。鎖定(Locking)發生在當一個事務獲得對某一資源的“鎖”時,這時,其他的事務就不能更改這個資源了,這種機制的存在是爲了保證數據一致性

 錯誤: Causedby:java.sql.BatchUpdateException: Deadlock found when trying to get lock;tryrestarting transaction 

 

產生死鎖的兩個必要條件:

1.使用事物

2.where 條件後面 一個是索引,一個不是索引

 

場景一:

sparkStreaming 在foreachportion(相當於多線程) 裏批量執行下面語句

updatebi_publish_back_cost set main_man='' where pkg_code='204022' andperformance_time='2017-05-22'

 

解決方法:

1.刪掉其中的一個索引就可以了

2.把兩個單獨索引改爲一個整體索引 (最終解決方法)

3.不使用事物

 

其他錯誤的嘗試:dobatch時,每  100 條execute一次,還是鎖住

 

場景二:

sparkStreaming 在foreachportion(相當於多線程) 裏批量執行下面語句

INSERT INTObi_gamepublic_base_day_kpi(parent_game_id,child_game_id,medium_channel,ad_site_channel,pkg_code,publish_date,new_regi_device_num)VALUES (?,?,?,?,?,?,?) ON DUPLICATE KEY updateos=?,group_id=?,medium_account=?,promotion_channel=?,promotion_mode=?,head_people=?,new_regi_device_num=new_regi_device_num+ VALUES(new_regi_device_num)

產生死鎖的原因: child_game_id,medium_channel,ad_site_channel,pkg_code中  child_game_id 和  pkg_code 爲 unique key ,執行這樣的語句,更新的時候 unique key  就相當於where,後續原因如場景一

解決方法:

1.把5個字段設置爲一個整體索引

2.不使用事物插入(最終解決方法)

 

死鎖解決方法總結:

1.多線程 批量更新數據庫的時候,where後面的限制條件要麼是同一索引,要不都不是索引,不要一般是索引,一半不是索引

2.不要使用 多線程事物插入

 

===多線程死鎖

public class DeadLocker {

public static void main(String[] args) {

DeadLock t1 = new DeadLock();

t1.setName("線程1");

DeadLock t2 = new DeadLock();

t2.setName("線程2");

t1.flag = true;

t2.flag = false;

t1.start();

t2.start();

}

}

 

class DeadLock extends Thread {

 

public boolean flag = true;

static Object o1 = new Object();// 定義兩個公共資源

static Object o2 = new Object();

 

@Override

public void run() {

// TODO Auto-generated method stub

if (flag) {

System.out.println(Thread.currentThread().getName() + "等待o1");

synchronized (o1) {

System.out.println(Thread.currentThread().getName() + "佔用o1,等待o2");

synchronized (o2) {

System.out.println(Thread.currentThread().getName() + "佔用o2");

}

System.out.println(Thread.currentThread().getName() + "釋放o2");

}

System.out.println(Thread.currentThread().getName() + "釋放o1");

} else {

System.out.println(Thread.currentThread().getName() + "等待o2");

synchronized (o2) {

System.out.println(Thread.currentThread().getName() + "佔用o2,等待o1");

synchronized (o1) {

System.out.println(Thread.currentThread().getName() + "佔用o1");

}

System.out.println(Thread.currentThread().getName() + "釋放o1");

}

System.out.println(Thread.currentThread().getName() + "釋放o2");

}

}

}

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章