資料庫出現死鎖怎麼辦?
阿新 • • 發佈:2021-02-05
前言
最近接到一個需求,需要同步二十萬條資料到我們資料庫來,然而過程並不太順利,解決之後來總結一下。
問題
同步的時候會報錯,導致同步失敗出現死鎖問題。
出現死鎖沒許可權,又不得不麻煩同事幫忙解開,關於解鎖直接百度即可http://blog.itpub.net/26812308/viewspace-2120485/
優化
後來瞭解情況後發現程式碼中沒有事務的相關處理,涉及到資料量很大如果出現網路波動或其他訪問操作同一張表就會容易引發死鎖問題。
PROCEDURE sync_mnt_five_tree IS
struction_2_t_num NUMBER;
struction_3_t_num NUMBER;
struction_4_t_num NUMBER;
struction_5_t_num NUMBER;
mm_contract_no_num NUMBER;
orgs_info_t_num NUMBER;
elevators_t_num NUMBER;
update_num NUMBER;
CURSOR v_cur IS
SELECT *
FROM [email protected] where ORG_ID is not null and AREA_ID is not null;
BEGIN
update_num :=0;
FOR v_row IN v_cur
LOOP
update_num := update_num+1;
--二級
SELECT COUNT(1)
INTO struction_2_t_num
FROM struction_2_t t
WHERE t.struction_2_id = to_char(v_row.mnt_contract_id);
IF struction_2_t_num > 0 THEN
UPDATE struction_2_t t
SET t. struction_2_name = v_row.customer_name, t.updated_by = 'system', t.updated_time = SYSDATE
WHERE t.struction_2_id = to_char(v_row.mnt_contract_id);
ELSE
INSERT INTO struction_2_t
(struction_2_id,
struction_2_code,
struction_2_name,
object_version,
created_by,
created_time,
updated_by,
updated_time)
VALUES
(to_char(v_row.mnt_contract_id), NULL, v_row.customer_name, 1, 'system', SYSDATE, 'system', SYSDATE);
END IF;
--三級
SELECT COUNT(1)
INTO struction_3_t_num
FROM struction_3_t t
WHERE t.struction_3_id = to_char(v_row.area_id);
IF struction_3_t_num > 0 THEN
UPDATE struction_3_t t
SET t.struction_3_name = v_row.area, t.updated_by = 'system', t.updated_time = SYSDATE
WHERE t.struction_3_id = to_char(v_row.area_id);
ELSE
INSERT INTO struction_3_t
(struction_3_id,
struction_3_code,
struction_3_name,
object_version,
created_by,
created_time,
updated_by,
updated_time)
VALUES
(to_char(v_row.area_id), NULL, v_row.area, 1, 'system', SYSDATE, 'system', SYSDATE);
END IF;
--四級
SELECT COUNT(1)
INTO struction_4_t_num
FROM struction_4_t t
WHERE t.struction_4_id = to_char(v_row.project_id);
IF struction_4_t_num > 0 THEN
UPDATE struction_4_t t
SET t.struction_4_name = v_row.project_name, t.updated_by = 'system', t.updated_time = SYSDATE
WHERE t.struction_4_id = to_char(v_row.project_id);
ELSE
INSERT INTO struction_4_t
(struction_4_id,
struction_4_code,
struction_4_name,
object_version,
created_by,
created_time,
updated_by,
updated_time)
VALUES
(to_char(v_row.project_id), NULL, v_row.project_name, 1, 'system', SYSDATE, 'system', SYSDATE);
END IF;
--五級
SELECT COUNT(1)
INTO struction_5_t_num
FROM struction_5_t t
WHERE t.struction_5_id = to_char(v_row.building_id);
IF struction_5_t_num > 0 THEN
UPDATE struction_5_t t
SET t.struction_5_name = v_row.building_name, t.updated_by = 'system', t.updated_time = SYSDATE
WHERE t.struction_5_id = to_char(v_row.building_id);
ELSE
INSERT INTO struction_5_t
(struction_5_id,
struction_5_code,
struction_5_name,
object_version,
created_by,
created_time,
updated_by,
updated_time)
VALUES
(to_char(v_row.building_id), NULL, v_row.building_name, 1, 'system', SYSDATE, 'system', SYSDATE);
END IF;
------
SELECT COUNT(1)
INTO mm_contract_no_num
FROM maintenance_message_t t
WHERE t.mm_contract_no = v_row.mnt_contract_no;
IF mm_contract_no_num > 0 THEN
UPDATE maintenance_message_t t
SET t.mm_start_time = v_row.begin_date,
t.mm_end_time = v_row.end_date,
t.updated_by = 'system',
t.updated_time = SYSDATE
WHERE t.mm_contract_no = v_row.mnt_contract_no;
ELSE
INSERT INTO maintenance_message_t
(mm_id,
mm_contract_no,
mm_start_time,
mm_end_time,
object_version,
created_by,
created_time,
updated_by,
updated_time)
VALUES
(to_char(v_row.mnt_contract_id),
v_row.mnt_contract_no,
v_row.begin_date,
v_row.end_date,
1,
'system',
SYSDATE,
'system',
SYSDATE);
END IF;
---------
SELECT COUNT(1)
INTO orgs_info_t_num
FROM orgs_info_t t
WHERE t.org_id = to_char(v_row.org_id);
IF orgs_info_t_num > 0 THEN
UPDATE orgs_info_t t
SET t.org_id = to_char(v_row.org_id),
t.org_syn_id = to_char(v_row.org_id),
-- t.org_name = v_row.
t.updated_by = 'system',
t.updated_time = SYSDATE
WHERE t.org_id = to_char(v_row.org_id);
ELSE
INSERT INTO orgs_info_t
(org_id, org_name, org_syn_id, object_version, created_by, updated_time, created_time, updated_by)
VALUES
(to_char(v_row.org_id), NULL, to_char(v_row.org_id), 1, 'system', SYSDATE, SYSDATE, 'system');
END IF;
---------
SELECT COUNT(1)
INTO elevators_t_num
FROM elevators_t t
WHERE t.ele_contract_no = v_row.ele_contract_no;
IF elevators_t_num > 0 THEN
UPDATE elevators_t t
SET t.ele_contract_no = v_row.ele_contract_no, t.updated_by = 'system', t.updated_time = SYSDATE
WHERE t.ele_contract_no = v_row.ele_contract_no;
ELSE
INSERT INTO elevators_t
(ele_contract_no, object_version, created_by, created_time, updated_by, updated_time)
VALUES
(v_row.ele_contract_no, 1, 'system', SYSDATE, 'system', SYSDATE);
END IF;
-----------每一千條提交一次
IF update_num > 1000 THEN
update_num :=0;
COMMIT;
END IF;
END LOOP;
COMMIT;
END;
總結
簡單做個計數器,每次迴圈進行加一,到達一千條資料commit一次,這樣能及時提交,減少衝突問題。