日期:2014-05-16 浏览次数:20645 次
最近在使用DB2的时候,老是出现57016的错误(由于表不活动,不能对表进行访问),特别是在数据导入和导出的时候,必定会出现,每次都要执行reorg一下。在reorg的过程中,如果该表有外键依赖,且外键表也不活动,就需要先对外键表进行reorg。
一次数据的导入,接近30%的表不能访问了,而且还有部分表的外键检查也被disable了,在reorg前,还要先恢复外键检查,非常麻烦。一个简单的办法是先删除所有外键,在reorg所有表之后再加上外键,但是这样还是可能在最后加外键的过程中表又不活动了。
所有我想对数据库的所有表按照外键依赖顺序进行排序,这样在reorg一张表之前,保证其依赖的外键表已经被reorg了。但是还是有一个问题,就是有些表有循环的外键依赖:对于这样的问题,只能通过先删除外键,reorg之后再加上。
下面是我用JAVA写的排序算法,包含了循环依赖检查(TableFK是一个非常简单的类,就不列出了):
package test; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; public class ReorgAllTable { private static final String SCHEMA = "TEST"; private final static String DB_URL = "jdbc:db2://localhost:50000/SIMPLE"; private final static String DB_DRIVER = "com.ibm.db2.jcc.DB2Driver"; private final static String DB_USERNAME = "TEST"; private final static String DB_PASSWORD = "TEST"; private Map<String, List<TableFK>> tableFKListMap = new HashMap<String, List<TableFK>>(); private Map<String, TableFK> tableFKMap = new HashMap<String, TableFK>(); private List<String> sortedTableList = new ArrayList<String>(); private Set<String> cycleFKSet = new HashSet<String>(); static { try { Class.forName(DB_DRIVER); } catch (Exception e) { throw new ExceptionInInitializerError(e); } } /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { ReorgAllTable reorgAllTable=new ReorgAllTable(); reorgAllTable.sortTableSet(); String sql = reorgAllTable.createSortedSql(); System.out.println(sql); } public void sortTableSet() throws Exception { fetchTableFkListMap(); Set<String> tableSet=tableFKListMap.keySet(); Iterator<String> tableSetIter = tableSet.iterator(); while (tableSetIter.hasNext()) { String table = tableSetIter.next(); sortTable(table, null); } } private void sortTable(String table, Set<String> pCycleCheckSet) { List<TableFK> tableFKList = getTableFKList(table); if (tableFKList == null || tableFKList.isEmpty()) { addTable(table); return; } for (TableFK tableFK : tableFKList) { String pTable = tableFK.PKTABLE_NAME; if (!sortedTableList.contains(pTable)) { // 循环依赖检查 Set<String> cycleCheckSet = new HashSet<String>(); if (pCycleCheckSet != null) { cycleCheckSet.addAll(pCycleCheckSet); } String fkName = tableFK.FK_NAME; if (!cycleCheckSet.contains(fkName)) { cycleCheckSet.add(fkName); } else { cycleFKSet.add(fkName); continue; } // 递归查找 sortTable(pTable, cycleCheckSet); // cycleCheckSet.clear(); cycleCheckSet = null; } } addTable(table); } private void addTable(String table) { if (!sortedTableList.contains(table)) { sortedTableList.add(table); } } private Map<String, List<TableFK>> fetchTableFkListMap() throws Exception { Connection connection = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD); DatabaseMetaData metaData = connection.getMetaData(); List<String> tableList = fetchTableList(connection,metaData); for (String table : tableList) { List<TableFK> tableFKList = new ArrayList<TableFK>(); ResultSet importedKeys = metaData.getImportedKeys(null, SCHEMA, table); while (importedKeys.next()) { TableFK tableFK = new TableFK(); tableFK.table = table; tableFK.PKTABLE_SCHEM = importedKeys.getString("PKTABLE_SCHEM");// 引用的外键表模式 tableFK.PKTABLE_NAME = importedKeys.getString("PKTABLE_NAME");// 引用的外键表名 tableFK.PKCOLUMN_NAME = importedKeys.getString("PKCOLUMN