前言:公司有开发环境数据库,生产环境数据库。小伙伴在开发环境更换了数据库字段,导致上线到生产环境时数据库字段不一致,所有写啦一个数据库对比工具分享给大家!!
public static final String SQLForGetTables = "select * from pg_tables WHERE schemaname='public'";
public static int tableAccount = 0;
public static int columnAccount = 0;
public static String tableMessage1 ;
public static String columnMessage ;
public static String errTable;
public static String db1 = "dmp";
public static String db2 = "dmp";
public static String IP1 = "0.0.0.14:30757";
public static String IP2 = "0.0.0.45:31150";
public static void main(String[] args) throws Exception {
//开发环境
Connection con1 = getConnection(IP1, db1, "postgres", "hello1234");
//生产环境
Connection con2 = getConnection(IP2, db2, "postgres", "hello1234");
// 查询出字段名称
List list = getInfos(con1, SQLForGetTables);
List list2 = getInfos(con2, SQLForGetTables);
System.out.println("将"+IP1+"的数据库"+db1+"与"+IP2+"数据库"+db2+"进行比较");
tableMessage1="数据库"+db2+"缺少的表为: ";
String res = checkTables(list, list2, con1, con2);
System.out.println(tableMessage1);
System.out.println("-------------------------比较完成");
System.out.println();
System.out.println("将"+IP2+"的数据库"+db2+"与"+IP1+"与数据库"+db1+"进行比较");
tableMessage1="数据库"+db1+"缺少的表为:";
res = checkTables(list2, list, con2, con1);
System.out.println(tableMessage1);
System.out.println("-------------------------比较完成");
System.out.println("这两个数据库中 有"+tableAccount+"个表不相同");
System.out.println("这两个数据库中 有"+columnAccount+"个字段不相同");
private static Connection getConnection(String ip, String dbName, String user, String pwd) throws ClassNotFoundException {
Connection con = null;
//String url1 = "jdbc:postgresql://10.70.21.14:30757/dmp";
String url1 = "jdbc:postgresql://"+ip+"/"+dbName+"";
Class.forName("org.postgresql.Driver");
try {
con = DriverManager.getConnection(url1, user, pwd);//如何用一个参数连接
} catch (SQLException e) {
System.out.println("开发环境数据库连接失败:" + e.getMessage());
return con;
// 比较两个LIST中的数据是否一致
@SuppressWarnings("rawtypes")
private static String checkTables(List list, List list2, Connection con1, Connection con2) {
// 先将数据库1的数据与2比较
int table = 0;
int colum = 0;
for (Object object : list) {
table = 0;
for (Object object2 : list2) {
if (object.equals(object2)) {
colum = checkDetail(object, object2, con1, con2);
table = 1;
continue;
if (table == 0) {
errTable = getName(object);
tableAccount++;
tableMessage1 = tableMessage1 + getName(object) + "; ";
table = 1;
continue;
if (table == 0 && colum == 0) {
return "两个数据库中表和字段一致";
if (table == 0 && colum == 1) {
return "两个数据库中表一致 字段不一致";
if (table == 1 && colum == 0) {
return "两个数据库中表不一致 字段一致";
} else
return "两个数据库中表不一致 字段也不一致";
// 比较两个表字段是否一致
@SuppressWarnings("rawtypes")
private static int checkDetail(Object object, Object object2, Connection con1, Connection con2) {
// 获得表的名字
String table = getName(object);
errTable = table;
String sql = "SELECT A.attname FROM pg_catalog.pg_attribute A WHERE 1 = 1 AND A.attrelid = ( SELECT oid FROM pg_class WHERE relname = '" + table + "' ) AND A.attnum > 0 AND NOT A.attisdropped ORDER BY A.attnum";
// 查询出字段名称
List list = getInfos(con1, sql);
List list2 = getInfos(con2, sql);
return checkColunm(list, list2);
// 检查表中的字段是否一致
@SuppressWarnings("rawtypes")
private static int checkColunm(List list, List list2) {
int res = 0;
for (Object object : list) {
int result = 0;
for (Object object2 : list2) {
// 如果这个字段在全部数据都匹配不到 则证明这个字段不匹配
if (object.equals(object2)) {
result = 1;
break;
if (result == 0) {
columnAccount++;
System.out.println("请注意 !表" + errTable + "中的" + getName(object) + "字段在后者数据库中没有");
res = 1;
return res;
// 根据OBJECT获得name的值
private static String getName(Object object) {
Map map = JSONObject.parseObject(JSONObject.toJSONString(object), Map.class);
return map.get("tablename")==null?map.get("attname")==null?"":map.get("attname").toString():map.get("tablename").toString();
// 查询数据库里面的表信息
@SuppressWarnings({"rawtypes", "unchecked"})
private static List getInfos(Connection con1, String sql) {
Statement stmt;
List list = new ArrayList();
try {
stmt = con1.createStatement();
ResultSet rs = stmt.executeQuery(sql);
ResultSetMetaData md = rs.getMetaData();
int columnCount = md.getColumnCount();
while (rs.next()) {
Map map = new HashMap();
for (int i = 1; i <= columnCount; i++) {
map.put(md.getColumnName(i), rs.getObject(i));
list.add(map);
} catch (SQLException e) {
System.out.println("查询数据库里面的表信息失败:" + e.getMessage());
e.printStackTrace();
return list;
pgcompare
适用于Linux,Mac OS X和Windows的Postgres数据库比较。
PG Compare将允许您比较两个Postgres数据库。 该应用程序不编写更改脚本,而是显示两个数据库模式之间的更改。 Tables和Functions是当前唯一被比较的架构对象。
该应用程序的外壳基于项目。 UI是使用呈现的。
缓存缓存对于数据库的系统性能有着重要意义。本文虽以Postgres为例,但也可对应到其他数据库系统。不同的计算机部件有着不同的运行速度。人类在理解数字的规模上面,与计算机有着极大的差距。对此,通过下面这张表格(截取自《文字间的无限空间》TheInfiniteSpaceBetweenWords),会有一个更直观的认识。表中数据是从人类角度加以估算。在数据库系统中,技术人员最关注的往往是硬盘的I/O问题。与新的固态硬盘(SSD)相比,磁盘在随机I/O方面的性能较差。大多数OLTP的工作负载都属于随机I/O,因此获取硬盘中信息时,速度就会极其缓慢。为了克服这一劣势,Postgres利用随机存取存储器
复制工具 (安装、配置)
一般工具 (磁盘使用情况、冗余索引、搜索元数据)
MySQL Utilities是一系列的命令行工具以及python库更容易完成管理的任务。库是用Python语言写的,这就意味着不需要安装其他任何工具和库。当前是基于Python2.6版本设计的,不支持Python3.1版本。
MySQL Uti
作者:阎书利
pgquarrel是一个PostgreSQL数据库的数据库结构(DDL)比对工具。它会对比两个数据库源,并输出一个表示DDL差异的文件。 如果将输出文件运行到目标数据库中,它将具有与源数据库相同的结构。 主要使用场景是将数据库更改部署到测试或生产环境。
pgquarrel不依赖于另一个工具(如pg_dump),而是直接连接到 PostgreSQL 服务器,从目录中获取元数据,比较对象并输出将目标数据库转换为源数据库所需的命令。它拥有过滤器选项:所以,可以比较部分对象。
它可以适用于不同的Pos
我们在实际开发的过程中,通常会有开发环境、测试环境、生产环境等。
在这些环境中,一般会有各自对应的数据库,由于每次新需求都是在测试环境中进行的测试,所以就会导致不同环境的数据库结构有不同。
当新一版本的功能在测试环境测好后,需要将新功能更新至生产环境,此时,生产环境数据库结构就需要再一次和测试环境数据库结构保持一致,才能保证新功能正常使用。
【数据库比较】
当我们想知道两个数据库的有哪些变化时候,如果每张表,每个字段的去比较,当在变化很大的时候,这将会是一个很不友好的体验,不但耗时耗
pgdiff-PostgreSQL模式差异
pgdiff比较两个PostgreSQL 9数据库之间的模式,并生成alter语句以针对第二个数据库手动运行以使其匹配。 提供的pgdiff.sh脚本有助于自动化该过程。
pgdiff的工作是透明的,因此它永远不会直接修改数据库。 在对数据库运行生成SQL之前,您自己一个人负责验证生成SQL。 继续,看看生成了什么SQL。
pgdiff被编写为易于扩展和提高diff的准确性。
下载1.0 beta 1
pgdiff [options] <schemaType>
(下面列出了选项和<schemaType>)
运行不同的架构类型似乎是一