Глобальный скрипт для удаления старых таблиц 2
Материал из BiTel WiKi
Глобальный скрипт для удаления старых таблиц (drop/truncate/dump)
Скрипт удаляет произвольные месячные или дневные таблицы в соответствии с настройками в глобальном конфиге биллинга:
#Скрипт удаления старых таблиц DropOldTables script.droptables.debug=0 #уведомление на email со списком удалённых таблиц script.droptables.email=admin@provider.ru #храним бэкапы script.droptables.dirbackup=/mnt/backup/ script.droptables.dumpstring=mysqldump -uroot -pbilling -P 3306 bgbilling
Удаляем (drop=1) или транкейтим (drop=0[default]) месячную таблицу старше 3 месяцев, при необходимости делаем дамп (backup=1):
script.droptables.month.1.prefix=log_server_12 script.droptables.month.1.months=3 script.droptables.month.1.drop=0 script.droptables.month.1.backup=0
Удаляем (drop=1) или транкейтим (drop=0[default]) дневную таблицу старше 3 месяцев, при необходимости делаем дамп (backup=1):
script.droptables.day.1.prefix=data_log_18 script.droptables.day.1.months=3 script.droptables.day.1.drop=1 script.droptables.day.1.backup=0
Делаем optimize table за 2 месяца, начиная с предыдущего:
script.droptables.optimize.month.1.prefix=log_session_18 script.droptables.optimize.month.1.months=2
Удаляем записи из session_detail модуля dialup, но только если по ним нет начислений в session_account (удаляем бесплатные трафики). Затем делаем Optimize table. В примере удаляются данные за 1 месяц старше 3 лет:
script.droptables.dialup.cleanup.1.mid=21 script.droptables.dialup.cleanup.1.months=37 script.droptables.dialup.cleanup.1.depth=1
package ru.dsi.bgbilling.kernel.scripts.global; import bitel.billing.server.util.MailMsg; import ru.bitel.bgbilling.kernel.script.server.dev.GlobalScriptBase; import ru.bitel.bgbilling.server.util.Setup; import ru.bitel.common.ParameterMap; import ru.bitel.common.sql.ConnectionSet; import java.io.IOException; import java.sql.*; import java.util.Calendar; import java.util.Map; import static ru.bitel.common.TimeUtils.*; /** * Чистим старые таблицы */ public class DropOldTables extends GlobalScriptBase { @Override public void execute( Setup setup, ConnectionSet connectionSet ) throws Exception { ParameterMap params = setup.sub("script.droptables."); String prefix; String name; int months; int flagDrop = 0; int backup = 0; Calendar cal; StringBuilder report = new StringBuilder(); boolean debug = params.getBoolean("debug", false); String email = params.get("email", null); String backupdir=params.get("dirbackup",null); String dumpstring=params.get("dumpstring",null); //daily //Подневные таблицы вида prefix_yyyymmdd // например, удаляем cdr-логи телефонии старше 6 месяцев (оставляем текущий + 5 предыдущих): //script.droptables.day.1.prefix=data_log_18 //script.droptables.day.1.months=6 for(Map.Entry<Integer, ParameterMap> entry: params.subIndexed("day.").entrySet()){ prefix = entry.getValue().get("prefix"); months = entry.getValue().getInt("months", 0); flagDrop = entry.getValue().getInt("drop", 0); backup = entry.getValue().getInt("backup", 0); if(prefix==null || months<=0){ error("'prefix' not found or 'months'<=0 for config params script.droptables.day."+entry.getKey()+"."); continue; } cal = Calendar.getInstance(); cal.add(Calendar.MONTH,-months); //Удаляем 12 месяцев начиная с now.mm-months for(int i=1;i<=12;i++) { for (int dd=1; dd<=cal.getActualMaximum(Calendar.DAY_OF_MONTH); dd++){ cal.set(Calendar.DAY_OF_MONTH, dd); name = prefix + format(cal, "_yyyyMMdd"); deleteRecord(connectionSet, name, flagDrop, report, backupdir, dumpstring, backup, debug); } cal.add(Calendar.MONTH,-1); } } //monthly //Помесячные таблицы вида prefix_yyyymm // например, удаляем radius-логи телефонии/dialup старше 6 месяцев (оставляем текущий + 5 предыдущих): //script.droptables.month.1.prefix=log_server_12 //script.droptables.month.1.months=6 for(Map.Entry<Integer, ParameterMap> entry: params.subIndexed("month.").entrySet()){ prefix = entry.getValue().get("prefix"); months = entry.getValue().getInt("months", 0); flagDrop = entry.getValue().getInt("drop", 0); backup = entry.getValue().getInt("backup", 0); if(prefix==null || months<=0){ error("'prefix' not found or 'months'<=0 for config params script.droptables.month."+entry.getKey()+"."); continue; } cal = Calendar.getInstance(); cal.add(Calendar.MONTH,-months); //Удаляем 12 месяцев начиная с now.mm-months for(int i=1;i<=12;i++) { name = prefix + format(cal, "_yyyyMM"); deleteRecord(connectionSet, name,flagDrop,report, backupdir, dumpstring, backup, debug); cal.add(Calendar.MONTH,-1); } } PreparedStatement ps; //monthly - optimize tables //Помесячные таблицы вида prefix_yyyymm // например, оптимизируем логи телефонии/dialup за 6 месяцев, начиная с предыдущего: //script.droptables.optimize.month.1.prefix=log_session_18 //script.droptables.optimize.month.1.months=6 for(Map.Entry<Integer, ParameterMap> entry: params.subIndexed("optimize.month.").entrySet()){ prefix = entry.getValue().get("prefix"); months = entry.getValue().getInt("months", 0); if(prefix==null || months<=0){ error("'prefix' not found or 'months'<=0 for config params script.droptables.optimize.month."+entry.getKey()+"."); continue; } cal = Calendar.getInstance(); cal.add(Calendar.MONTH,-1); //Optimize 12 месяцев начиная с now.mm-months for(int i=1;i<=months;i++) { name = prefix + format(cal, "_yyyyMM"); if(tableExists(connectionSet.getConnection(), name)) { ps = connectionSet.getConnection().prepareStatement("optimize table "+name); ps.executeUpdate(); ps.close(); print("OPTIMIZE TABLE "+name); report.append("OPTIMIZE TABLE ").append(name).append("\n"); } cal.add(Calendar.MONTH,-1); } } //monthly - удаляем бесплатные трафики из session_detail_mid_yyyymm модуля dialup //например, чистим трафики в таблицах старше 3 лет глубиной в 1 месяц и сразу делаем optimize //script.droptables.dialup.cleanup.1.mid=21 //script.droptables.dialup.cleanup.1.months=36 //script.droptables.dialup.cleanup.1.depth=1 //script.droptables.dialup.cleanup.1.optimize=1 int mid; int depth; int optimize; for(Map.Entry<Integer, ParameterMap> entry: params.subIndexed("dialup.cleanup.").entrySet()){ mid = entry.getValue().getInt("mid",0 ); months = entry.getValue().getInt("months", 0); depth = entry.getValue().getInt("depth", 1); optimize = entry.getValue().getInt("optimize", 1); if(mid<=0 || months<=0){ error("'mid' or 'months'<=0 for config params script.droptables.dialup.cleanup."+entry.getKey()+"."); continue; } cal = Calendar.getInstance(); cal.add(Calendar.MONTH,-months); //Optimize depth месяцев начиная с now.mm-months int max_cid; int min_cid; int row_count; int counter; ResultSet rs; for(int i=1;i<=depth;i++) { name = "session_detail_"+mid + format(cal, "_yyyyMM"); if(tableExists(connectionSet.getConnection(), name)) { //Будем делать delete кусочками. limit в mysql нельзя использовать в delete с join. //Поэтому удаляем с отсечкой по индексному полю cid с градацией в 1000 cid-ов ps = connectionSet.getConnection().prepareStatement("select max(cid) from "+name); rs = ps.executeQuery(); max_cid = 0; if(rs.next()){ max_cid = rs.getInt(1); } rs.close(); ps.close(); ps = connectionSet.getConnection().prepareStatement("select min(cid) from "+name); rs = ps.executeQuery(); min_cid = 0; if(rs.next()){ min_cid = rs.getInt(1); } rs.close(); ps.close(); row_count=0; counter=0; for(int id=max_cid-1000; id>min_cid-1000;id-=1000) { ps = connectionSet.getConnection().prepareStatement("delete d from " + name + " d " + "left join session_account_" + mid + format(cal, "_yyyyMM") + " a on d.session_id=a.session_id and d.sid=a.sid " + "where a.session_id is null and d.cid>="+id); row_count+=ps.executeUpdate(); counter++; ps.close(); } print("* delete ~~~ from TABLE " + name+" ["+row_count+" rows, "+counter+" iterations]"); report.append("* delete ~~~ from TABLE ").append(name).append("\n"); if(optimize==1) { ps = connectionSet.getConnection().prepareStatement("optimize table " + name); ps.executeUpdate(); ps.close(); print("OPTIMIZE TABLE " + name); report.append("OPTIMIZE TABLE ").append(name).append("\n"); } } cal.add(Calendar.MONTH,-1); } } if(email!=null && !"".equals(email)){ MailMsg msg = new MailMsg(setup); msg.sendMessage(email, "Удаление старых таблиц", report.toString()); } } private void deleteRecord(ConnectionSet connectionSet, String tableName, int flagDrop, StringBuilder report, String backupdir, String dumpstring, int backup, boolean debug){ if(tableExists(connectionSet.getConnection(), tableName)) { String trorDrop=flagDrop==0?"TRUNCATE":"DROP TABLE"; String filedm=backupdir+"/"+tableName; print(trorDrop+" " + tableName); if (!debug){ int exitValue=1; if(backup==1){ Runtime rt = Runtime.getRuntime(); String commandDump = dumpstring+" "+tableName+" -r "+ filedm+".sql"; String commandZip = " zip "+filedm+".zip "+filedm+".sql"; String commandRm = "rm "+filedm+".sql"; try { Process proc=rt.exec(commandDump); proc.waitFor(); if (proc.exitValue()==0){ proc=rt.exec(commandZip); proc.waitFor(); if(proc.exitValue()==0){ proc=rt.exec(commandRm); proc.waitFor(); } } exitValue=proc.exitValue(); } catch (IOException e) { error("Не удалось сделать бэкап таблицы " + tableName+"; Exeption : "+e.toString()); } catch (InterruptedException e) { error("Не удалось сделать бэкап таблицы " + tableName+"; Exeption : "+e.toString()); } } if((backup==1&&exitValue==0)||(backup==0)){ try { Statement st = connectionSet.getConnection().createStatement(); st.executeUpdate(trorDrop+" " + tableName); st.close(); }catch (SQLException e){ error(e.getMessage()); } } } report.append(trorDrop).append(" ").append(tableName).append("\n"); } } private boolean tableExists(Connection con, String tableName){ boolean result=false; try { PreparedStatement ps = con.prepareStatement("SHOW TABLES LIKE ?"); ps.setString(1, tableName); ResultSet rs = ps.executeQuery(); result = rs.next(); rs.close(); ps.close(); } catch (SQLException e) { e.printStackTrace(); } return result; } }
Пример конфига скрипта:
#Скрипт удаления старых таблиц DropOldTables script.droptables.debug=0 #уведомление на email со списком удалённых таблиц script.droptables.email=admin@provider.ru #храним бэкапы script.droptables.dirbackup=/mnt/backup/bgtables script.droptables.dumpstring=mysqldump -uroot -p12345 -P 3306 -h 127.0.0.1 bgbilling script.droptables.month.1.prefix=log_server_1 script.droptables.month.1.months=6 script.droptables.month.2.prefix=log_error_1 script.droptables.month.2.months=6 script.droptables.month.3.prefix=log_function_process script.droptables.month.3.months=6 script.droptables.month.4.prefix=connection_log_entry_28 script.droptables.month.4.months=6 script.droptables.month.5.prefix=inet_auth_error_28 script.droptables.month.5.months=6 script.droptables.month.6.prefix=log_gscript_process script.droptables.month.6.months=6 script.droptables.month.6.drop=1 script.droptables.month.7.prefix=npay_add_cost_detail_16 script.droptables.month.7.months=6 script.droptables.month.7.drop=1 script.droptables.month.8.prefix=npay_detail_16 script.droptables.month.8.months=24 script.droptables.month.8.drop=1 script.droptables.month.9.prefix=source_data script.droptables.month.9.months=9 script.droptables.month.9.drop=1 script.droptables.month.10.prefix=tariff_detail_1 script.droptables.month.10.months=6 script.droptables.month.10.drop=1 script.droptables.month.11.prefix=bgs_query_log script.droptables.month.11.months=12 script.droptables.month.11.drop=1 script.droptables.month.11.backup=1 script.droptables.month.12.prefix=web_query_log script.droptables.month.12.months=6 script.droptables.month.12.drop=1 script.droptables.month.12.backup=1 script.droptables.day.1.prefix=data_log_18 script.droptables.day.1.months=3 script.droptables.day.1.drop=1 script.droptables.optimize.month.1.prefix=log_session_18 script.droptables.optimize.month.1.months=2 script.droptables.optimize.month.2.prefix=log_session_29 script.droptables.optimize.month.2.months=2 script.droptables.dialup.cleanup.1.mid=21 script.droptables.dialup.cleanup.1.months=37 script.droptables.dialup.cleanup.1.depth=1 #
--Cromeshnic 07:40, 1 августа 2018 (UTC)