`
jzy996492849
  • 浏览: 128114 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

自动监控MySQL表结构变更脚本

 
阅读更多
摘要: 如何监控MySQL数据库表结构和表变更,并通知到相关的联系人、实现报警或通知? 由于平台采用django系统实现,因此通过如下代码实现(代码low,也可以写成python文件,传参数执行): 简单思路: 对用户指定库的所有列值进行md5,并存储到本地数据库,每次定时执行,校对md5,并找出不匹配的进行判断 会自动找出新增、删除、变更表结构的表# models.

如何监控MySQL数据库表结构和表变更,并通知到相关的联系人、实现报警或通知?

由于平台采用django系统实现,因此通过如下代码实现(代码low,也可以写成python文件,传参数执行):
简单思路:
对用户指定库的所有列值进行md5,并存储到本地数据库,每次定时执行,校对md5,并找出不匹配的进行判断
会自动找出新增、删除、变更表结构的表

# models.py



class MonitorSchema(models.Model):
    table_schema = models.CharField(null=False, max_length=512)
    table_name = models.CharField(null=False, max_length=512)
    table_stru = models.TextField(null=False, default='')
    md5_sum = models.CharField(null=False, max_length=256)

    class Meta:
        verbose_name = u'监控表结构变更表'
        verbose_name_plural = verbose_name
        permissions = ()
        db_table = "dbaudit_monitor_schema"




# tasks.py


import datetime
import hashlib
import difflib

import mysql.connector as mdb
from celery import shared_task
from django.core.mail import EmailMessage
from django.template.loader import render_to_string

from auditdb.settings import EMAIL_FROM


@shared_task
def schema_modify_monitor(**kwargs):
    check_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    conn = connect_db(**kwargs)
    cursor = conn.cursor(dictionary=True)

    query_info = "select table_schema,table_name,group_concat(COLUMN_NAME) as column_name," \
                 "group_concat(COLUMN_DEFAULT) as column_default,group_concat(IS_NULLABLE) as is_nullable," \
                 "group_concat(DATA_TYPE) as data_type,group_concat(CHARACTER_MAXIMUM_LENGTH) as char_length," \
                 "group_concat(COLUMN_TYPE) as column_type,group_concat(COLUMN_COMMENT) as column_comment " \
                 "from columns where table_schema='{schema}' " \
                 "group by table_schema,table_name".format(schema=kwargs['schema'])

    cursor.execute(query_info)

    source_info = []
    table_list = []
    diff_old_data = ''
    diff_new_data = ''
    table_change_data = []

    for row in cursor.fetchall():
        table_schema = row['table_schema']
        table_name = row['table_name']

        md5_source = ''.join(str(row.values()))
        md5_sum = hashlib.md5(md5_source.encode('utf8')).hexdigest()
        source_info.append({'table_schema': table_schema, 'table_name': table_name, 'md5_sum': md5_sum})
        table_list.append(table_name)

    # 如果当前库没有记录,则进行初始化全量同步
    if MonitorSchema.objects.filter(table_schema=kwargs['schema']).first() is None:
        for row in source_info:
            table_schema = row['table_schema']
            table_name = row['table_name']

            query_table_stru = "show create table {}".format('.'.join((table_schema, table_name)))
            cursor.execute(query_table_stru)
            for i in cursor:
                table_stru = i['Create Table']
                row['table_stru'] = str(table_stru)
                MonitorSchema.objects.create(**row)
    else:
        # 如果存在,开始核验数据
        old_data = list(MonitorSchema.objects.filter(table_schema=kwargs['schema']).values_list('table_name', flat=True))
        new_data = table_list

        # 找出已删除的表,并处理
        table_remove = list(set(old_data).difference(set(new_data)))
        if table_remove:
            table_change_data.append({'remove': table_remove})
            # 从本地库中删除该表的记录
            MonitorSchema.objects.filter(table_schema=kwargs['schema']).filter(table_name__in=table_remove).delete()

        # 找出新增的表,并处理
        table_add = list(set(new_data).difference(set(old_data)))
        if table_add:
            for i in table_add:
                for j in source_info:
                    if i in j.values():
                        table_change_data.append({'add': j})
                        table_schema = j['table_schema']
                        table_name = j['table_name']
                        query_table_stru = "show create table {}".format('.'.join((table_schema, table_name)))
                        cursor.execute(query_table_stru)
                        for x in cursor:
                            table_stru = x['Create Table']
                            j['table_stru'] = str(table_stru)
                            MonitorSchema.objects.create(**j)

        # 找出相同的表,并核验表结构
        table_intersection = list(set(old_data).intersection(set(new_data)))
        for row in source_info:
            table_schema = row['table_schema']
            table_name = row['table_name']
            new_md5_sum = row['md5_sum']

            if table_name in table_intersection:
                old_table = MonitorSchema.objects.get(table_schema=table_schema, table_name=table_name)
                if new_md5_sum != old_table.md5_sum:
                    query_table_stru = "show create table {}".format('.'.join((table_schema, table_name)))
                    cursor.execute(query_table_stru)
                    for i in cursor:
                        table_stru = i['Create Table']
                        diff_old_data += old_table.table_stru + '\n'*3
                        diff_new_data += table_stru + '\n'*3
                        # 更新新表表结构到本地
                        MonitorSchema.objects.update_or_create(table_schema=table_schema, table_name=table_name,
                                                               defaults={'table_stru': table_stru,
                                                                         'md5_sum': new_md5_sum})

    if (diff_old_data and diff_new_data) or table_change_data:
        html_data = ''
        if diff_old_data and diff_new_data:
            diff_data = difflib.HtmlDiff(tabsize=2)
            old_table_stru = list(diff_old_data.split('\n'))
            new_table_stru = list(diff_new_data.split('\n'))
            html_data = diff_data.make_file(old_table_stru, new_table_stru, '旧表-表结构', '新表-表结构', context=False,
                                            numlines=5)

        email_html_body = render_to_string('_monitor_table.html', {'html_data': html_data, 'table_change_data': table_change_data})
        title = '{db}库表变更[来自:{host},检测时间:{check_time}]'.format(db=kwargs['schema'], host=kwargs['describle'], check_time=check_time)
        msg = EmailMessage(subject=title,
                           body=email_html_body,
                           from_email=EMAIL_FROM,
                           to=kwargs['receiver'].split(','),
                           )
        msg.content_subtype = "html"
        msg.send()
    cursor.close()
    conn.close()




对应的html文件:

# _monitor_table.html



<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <style>
        body {
            font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
            font-size: 12px;
            line-height: 1.42857143;
            color: #333;
        }

        .box.box-primary {
            border-top-color: #3c8dbc;
        }

        .box {
            position: relative;
            border-radius: 3px;
            background: #ffffff;
            border-top: 3px solid #d2d6de;
            margin-bottom: 20px;
            width: 100%;
            box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
        }

        .panel-danger > .panel-heading {
            color: #a94442;
            background-color: #f2dede;
            border-color: #ebccd1;
        }

        .panel-info > .panel-heading {
            color: #31708f;
            background-color: #d9edf7;
            border-color: #bce8f1;
        }

        .panel-success > .panel-heading {
            color: #3c763d;
            background-color: #dff0d8;
            border-color: #d6e9c6;
        }

        .panel-heading {
            padding: 6px 8px;
            border-bottom: 1px solid transparent;
            border-top-left-radius: 3px;
            border-top-right-radius: 3px;
        }

        .panel-body {
            padding: 6px;
            color: #3c763d;
            background-color: #f5f5f5;
        }
    </style>
</head>
<body>
<div class="box box-primary">
    <p>各位同仁好:</p>
    <p>  表结构变更如下,请查阅,谢谢。</p>

    {% if table_change_data %}
        {% for row in table_change_data %}
            {% if row.remove %}
                <div class="panel panel-danger">
                    <div class="panel-heading">删除的表</div>
                    <div class="panel-body">
                        {% for j in row.remove %}
                            {{ j }}
                        {% endfor %}
                    </div>
                </div>
            {% endif %}
        {% endfor %}

        {% for row in table_change_data %}
            {% if row.add %}
                <div class="panel panel-info">
                    <div class="panel-heading">新增的表:{{ row.add.table_name }}_[表结构]</div>
                    <div class="panel-body">
                        <pre>{{ row.add.table_stru }}</pre>
                    </div>
                </div>
            {% endif %}
        {% endfor %}
    {% endif %}

    {% if html_data %}
        <div class="panel panel-success">
            <div class="panel-heading">变更的表结构[左侧为变更前表结构、右侧为变更后表结构、标色部分为差异]</div>
            <div class="panel-body">
                {{ html_data|safe }}
            </div>
        </div>
    {% endif %}

</div>
</body>
</html>

最后在django后台添加定时任务或者轮询任务

邮件输出结果:
fbabeb503b7b334e82796db18be8463a403d1fd8
72310593bc9158613ee3796b72c823f9cbc18138


版权声明:本文内容由互联网用户自发贡献,本社区不拥有所有权,也不承担相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:yqgroup@service.aliyun.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
分享到:
评论

相关推荐

    Python-Facebook开源在线MySQL表结构变更工具OnlineSchemaChange

    **Python-Facebook开源在线MySQL表结构变更工具OnlineSchemaChange** MySQL是世界上最受欢迎的开源关系型数据库管理系统之一,但在生产环境中对表结构进行变更时,往往需要停服或者面临数据不一致的风险。为了解决...

    8、NIFI综合应用场景-NiFi监控MySQL binlog进行实时同步到hive

    在本场景中,我们将探讨如何使用NiFi来实时监控MySQL数据库的binlog(二进制日志),并将其中的变更事件同步到Hive数据仓库。由于Hive的插入操作效率较低,这种方案通常不用于直接的实时写入,但可以作为数据流处理...

    MySQL如何快速修改表的表结构

    除了上述介绍的方法外,还有一些第三方工具和脚本能够帮助自动化执行这些操作,例如使用脚本监控数据库模式变更并执行相应的表结构同步。但无论采用哪种方法,对于数据库表结构的修改都应该谨慎操作,因为在修改过程...

    mysql-workbench.zip

    1. **数据建模**:理解如何创建ER图,定义表结构,设置主键和外键,以及创建索引。 2. **SQL开发**:熟悉SQL语法,利用Workbench的代码编辑器进行高效编程。 3. **数据库管理**:学习如何查看和调整数据库配置,监控...

    mysql的管理工具

    8. Percona Toolkit:Percona提供了一系列命令行工具,包括pt-online-schema-change(在线表结构变更)、pt-query-digest(查询日志分析)等,用于高性能MySQL环境的管理和优化。 9. Zabbix:虽然主要是一款网络...

    Facebook针对MySQL开源Online Schema Change代码

    Online Schema Change是一种允许在不影响应用程序正常运行的情况下更改数据库表结构的技术。Facebook开源的这一工具,旨在简化这一过程,减少潜在的数据丢失风险,同时最小化对业务的影响。以下是对Facebook开源的On...

    mysql-8.0.21-el7-x86-64.tar.gz

    对于生产环境,还应考虑使用如`mysqldump`进行备份,`pt-online-schema-change`进行在线表结构变更,以及`percona-toolkit`等性能优化工具。同时,理解并正确配置MySQL的系统变量和配置文件`my.cnf`对于优化性能至关...

    mysql历史数据同步到clickhouse 已测试

    在设计表结构时,需要根据查询需求,将经常一起使用的列放在一起,以提高查询效率。 - **分区策略**: ClickHouse支持多种分区策略,如按时间戳、哈希等进行分区,以优化数据分布和查询性能。针对历史数据,通常会...

    跟益达学Solr5之增量索引MySQL数据库表数据

    在这个过程中,`mobile.sql`文件可能是用于初始化或测试MySQL数据库的脚本,包含创建表结构、插入初始数据等内容。在实践过程中,可以使用类似的脚本来模拟数据变化,以便于测试Solr的增量索引功能。 总的来说,...

    【ssm项目源码】超市管理系统,包含mysql数据库脚本文件.zip

    这个系统包含了MySQL数据库脚本文件,这意味着它依赖于MySQL作为后端数据存储,且在部署前需要执行SQL脚本来创建对应的数据库表结构。 首先,Spring框架是整个系统的基石,它负责依赖注入(Dependency Injection, ...

    根据mysql慢日志监控SQL语句执行效率

    启用慢查询日志后,你可以定期检查这个日志文件,找出那些运行时间过长的SQL语句,分析它们的执行计划,考虑是否可以通过优化查询语句、创建索引或者调整表结构来提升查询效率。还可以使用MySQL自带的`EXPLAIN`...

    mysql企业管理器

    2. **表结构设计**:设计数据库表的结构是数据库开发的核心部分。在MySQL企业管理器中,你可以直观地创建、修改和删除表字段,设置主键、外键、索引和触发器,确保数据完整性和一致性。 3. **数据操作**:该工具...

    MySQL DBA从入门到精通笔记

    MySQL DBA从入门到精通的过程,涵盖了数据库安装配置、备份与恢复、数据类型选择、数据完整性保证、表结构变更、性能优化等多个方面。DBA在实践中的每一步都离不开对MySQL基础的理解和对高级技术的掌握。通过不断...

    canal实现mysql到ES数据实时同步

    - 在Canal Adapter的配置文件中,定义需要同步的MySQL表及其映射到Elasticsearch的规则。 - 可以通过注解或XML文件定义转换规则,比如字段映射、过滤条件等。 5. **启动Canal Adapter**: - 运行Canal Adapter的...

    Mysql可视化管理工具

    3. **服务器管理**:MySQL Workbench允许连接到本地或远程MySQL服务器,进行配置、监控和管理任务。你可以查看服务器状态、管理用户权限、备份数据库、优化表等。 4. **逆向工程**:如果已有现有的数据库,你可以...

    EMS for mysql

    EMS for MySQL支持版本跟踪,可以方便地比较和合并数据库结构的变更。 9. **安全性管理** 用户可以管理MySQL用户的权限,分配角色,设置访问限制,确保数据库的安全性。 10. **多语言支持** 作为一款国际化的...

    mysql可视化工具.zip

    4. **数据库设计**:可视化工具可以帮助设计数据库模式,包括创建、修改表结构,定义主键、外键关系,以及视图和存储过程等。 5. **数据导入导出**:工具支持从CSV、Excel或其他数据库格式导入数据到MySQL,也可以...

    Toad-for-MySQL-Freeware_6.01

    同时,它的数据库设计工具允许用户创建和修改数据库模式,包括表结构、索引和外键约束,有助于保持数据库的规范化和一致性。 性能监控是Toad的另一大亮点。它提供了实时的性能仪表板,可以监控数据库的CPU使用、...

    nacos-mysql

    当Nacos或MySQL有新版本发布时,需要关注新版本对数据存储的变更,可能需要更新数据库的结构或数据迁移。 10. **故障恢复**: 针对可能出现的故障,如MySQL服务中断,应有备份恢复策略,确保Nacos服务的连续性。 ...

Global site tag (gtag.js) - Google Analytics