最近有乙個場景,在生產環境的乙個庫中,新增了乙個字段。需要從另乙個關聯表中找到相當的字段回填。
影響資料數百萬條。
首先,不能使用一條大的update語句來更新,這個鎖太大,容易產生鎖徵用,造成死鎖。
update b a set new_column=(select other_col from a b where status=9 and a.busi_id=b.busi_id and b.pid=1242343324),modified=now() where pid=21343
因此,寫乙個儲存過程解決,儲存過程一條條處理,太慢且消耗本地io,所以寫了個批量更新的儲存過程。
如下:delimiter &&
create procedure updatetimev1(in comcount bigint)
begin
#routine body goes here...
declare i int;
set i=0;
set @sum=(select count(distinct busi_id
) from `b` where `pid`=1242343324 and status=9 );
set @log = "log query ....";
select concat(@log,@sum," 條");
while i<=@sum do
set i=i+1;
set @busi_id =( select distinct busi_id from `a` where `pid`=1242343324 limit i,1);
set @other_col
=(select other_col
from `b` where `pid`=1242343324 and yn =1 and `busi_id
` = @busi_id
limit 1);
if @busi_id is null then
select concat(@log," busi_id is null");
elseif @other_col is null then
select concat(@log," other_col is null");
else
#start transaction;
/** 關閉事務的自動提交 */
set autocommit = 0;
update a set new_column =@other_col,modified = now() where `pid`=1242343324 and busi_id=@busi_id and status =15;
## if mod(i,comcount)=0 then commit;
if mod(i,1000)=0 then commit;
end if;
end if;
end while;
commit; #最後不足1000條時提交
set autocommit = 1;
end&&
delimiter ;
上面的儲存過程效率還不夠快,並且limit i,1會導致,儲存過程在執行到中間某一時刻後會取不到資料,導致漏資料。根據經驗值,如果影響資料量在500w之內,可以直接游標取出來更新,而且不會有漏掉的。另外,根據經驗值,批量提交3000到5000是可以的,當然保險期間可以1000到2000提交一次。
修改後的儲存過程正下:
delimiter &&
create procedure updatetimev2(in comcount bigint)
begin
declare c_busi_id
bigint(20);
declare i int default 0;
declare cur_award cursor for
select distinct busi_id
from `a` where `pid`=1242343324
and yn =1 and order_time is null ;
open cur_award;
loop
fetch cur_award into c_busi_id
;set i=i+1;
set @other_col =(select cast(other_col as date) from `b` where `platform_id`=1242343324
and yn =1 and `busi_id
` = c_busi_id
limit 1);
if @other_col is null then
select concat(@log," other_col is null");
else
set autocommit = 0;
select concat("before update c_busi_id
is ",c_busi_id
," other_col is ",@other_col);
update a set order_time =@other_col,modified = now() where `pid`=1242343324
and busi_id
=c_busi_id
and yn =1;
select concat("after update c_busi_id
is ",c_busi_id
);if mod(i,comcount)=0 then
select concat("befor update commit i is ",i);
commit;
end if;
end if;
end loop;
commit;
set autocommit = 1;
end&&
delimiter ;
經測試優化後的儲存過程的效能要遠遠優化優化前的,且不會漏記錄。
備註:1、測試了一下一條一條執行,一小時大概20w行更新
2、mod(i,1000)
這塊得注意 ,如果把set i=i+1;
放到最後,在上面的儲存過程批量就不會生效。
3、刪除儲存過程drop procedure updatetimev1;
Solr部署配置(四)批量匯入資料
一 solr自帶匯入外掛程式dataimporte設定 1 在solrconfig.xml檔案中新增如下內容,引入dataimport功能,並設定配置檔案位置。d dev test solr tomcat solr db conf db data config.xml 二 匯入資料 1 從資料庫匯入...
unittest單元測試框架(四)批量執行測試用例
批量執行測試用例,比較合理的做法是把相關的幾條用例放到乙個.py 檔案裡,把所有.py 檔案放到乙個資料夾下,然後通過乙個程式執行資料夾下面的所有用例。testcase.py dos命令一直有錯。如果大家對於學習python有任何問題,學習方法,學習路線,如何學習有效率的問題,可以隨時來諮詢我,或者...
mysql 儲存過程批量更新
最近做乙個批量更新的操作,由於是臨時需求,就想著在資料庫直接操作,不在 裡動手了,結合網上的一些資料,做如下處理 1.先建立乙個臨時表,匯入需要變動的資料 drop table if exists t barcode create table t barcode barcode varchar 32...