MySQL校验和到数据库中的所有表

时间:2018-02-02 01:49:53

标签: mysql

我正在评估基于PHP / MySQL的软件。 我想查看某些操作触发时哪些表会受到影响。

经过一些谷歌搜索,我被告知checksum table tbl_name可以完成这项工作。我只需要知道如何对db中的所有表使用checksum

对于checksum所有表一个一个地手动绝对不是首选,因为数据库包含数百个表。

5 个答案:

答案 0 :(得分:3)

检查所有表似乎只是为了检测哪些表发生了变化而进行了大量昂贵的计算工作。

我建议使用sys.schema_table_statistics表格获取此信息。

mysql> select table_schema, table_name, rows_fetched, rows_inserted, rows_updated, rows_deleted 
  from sys.schema_table_statistics where table_schema='test'
+--------------+---------------------+--------------+---------------+--------------+--------------+
| table_schema | table_name          | rows_fetched | rows_inserted | rows_updated | rows_deleted |
+--------------+---------------------+--------------+---------------+--------------+--------------+
| test         | sysbench_results    |          870 |           144 |            0 |            0 |
+--------------+---------------------+--------------+---------------+--------------+--------------+

您可能希望重置测试之间的计数器。使用sys.ps_truncate_all_tables()

mysql> call sys.ps_truncate_all_tables(FALSE);
+---------------------+
| summary             |
+---------------------+
| Truncated 31 tables |
+---------------------+

mysql> select table_schema, table_name, rows_fetched, rows_inserted, rows_updated, rows_deleted
  from sys.schema_table_statistics where table_schema='test';
+--------------+---------------------+--------------+---------------+--------------+--------------+
| table_schema | table_name          | rows_fetched | rows_inserted | rows_updated | rows_deleted |
+--------------+---------------------+--------------+---------------+--------------+--------------+
| test         | sysbench_results    |            0 |             0 |            0 |            0 |
+--------------+---------------------+--------------+---------------+--------------+--------------+

sys 5.7已预先安装在MySQL 5.7中。

如果您使用MySQL 5.6,则可能需要自行安装。它只是一个SQL脚本,可以在performance_schema中创建一些视图。非常容易安装。

您可以在此处获取sys架构:https://github.com/mysql/mysql-sys

答案 1 :(得分:2)

  

我想查看某些操作触发时哪些表会受到影响。

这是什么意思?

您是否知道触发了哪些操作,而您只是想了解它们对您的数据库有何影响(例如验证其正确性)?或者您不知道触发了哪些操作(例如在某个时间间隔内),但您仍想了解数据库的更改方式,也许是为了确定这些操作是什么?

在极少数情况下,我希望最好的方法是您正在探索的方法(检查数据库的更改)。相反,某些形式的日志记录 - 是否内置于RDBMS(例如MySQL的General Query Log或者可能通过Sumesh建议的triggers),或更可能在某些更高的位置级别(例如在访问应用程序中) - 几乎总是更可取。这使我倾向于认为你有一个XY Problem

但是,假设您确实想要识别自上次已知的良好时间点以来已修改的表,您可以查询INFORMATION_SCHEMA.TABLES表,其中不仅包含CHECKSUM对于RDBMS中的每个表,还有其他可能有用的信息,如UPDATE_TIME。因此,例如,要识别在过去五分钟内更改的所有表,可以执行以下操作:

SELECT TABLE_SCHEMA, TABLE_NAME
FROM   INFORMATION_SCHEMA.TABLES
WHERE  UPDATE_TIME > NOW() - INTERVAL 5 MINUTE

答案 2 :(得分:1)

您可以为所有表生成CHECKSUM语句:

SELECT CONCAT('CHECKSUM TABLE ', table_name, ';') AS statement
FROM information_schema.tables
WHERE table_schema = 'YourDBNameHere'

然后复制此输出并将其粘贴到Workbench或您需要使用的任何工具中。如果您需要在应用程序(例如PHP)代码中执行此操作,那么您可能必须使用纯动态MySQL。

答案 3 :(得分:1)

对于那些来这里回答问题的人,如何在一个查询中为所有表获取checksum(就像我的情况一样):

SET group_concat_max_len = CAST( 
    (  
        SELECT SUM(LENGTH(TABLE_NAME)) + COUNT(*) * LENGTH(', ') 
        FROM information_schema.tables WHERE `TABLE_SCHEMA` = 'your_database_name' 
    ) AS UNSIGNED
);

SET @sql_command:= ( 
    SELECT CONCAT( 
        'CHECKSUM TABLE ', 
        GROUP_CONCAT( TABLE_NAME ORDER BY `TABLE_NAME` SEPARATOR ', ' ) 
    )
    FROM information_schema.tables 
    WHERE `TABLE_SCHEMA` = 'your_database_name' 
    ORDER BY `TABLE_NAME` 
);

PREPARE statement FROM @sql_command;
EXECUTE statement;
DEALLOCATE PREPARE statement;

一个简单的想法是创建CHECKSUM TABLE语句,其中包含所有表名。是的,这是Tim Biegeleisen给出的answer的一点点升级版本。

首先,我们为GROUP_CONCAT()函数设置最大允许结果长度(默认为1024字节)。它是根据所有表名中包含分隔符的符号数计算的,这些分隔符将放在这些名称之间:

SET group_concat_max_len = CAST( 
    (  
        SELECT SUM(LENGTH(TABLE_NAME)) + COUNT(*) * LENGTH(', ') 
        FROM information_schema.tables WHERE `TABLE_SCHEMA` = 'your_database_name' 
    ) AS UNSIGNED
);

然后,我们将所有表名称放在一个CHECKSUM TABLE语句中,并将其存储在字符串变量中:

SET @sql_command:= ( 
    SELECT CONCAT( 
        'CHECKSUM TABLE ', 
        GROUP_CONCAT( TABLE_NAME ORDER BY `TABLE_NAME` SEPARATOR ', ' ) 
    )
    FROM information_schema.tables 
    WHERE `TABLE_SCHEMA` = 'your_database_name' 
    ORDER BY `TABLE_NAME` 
);

最后执行该语句以查看结果:

PREPARE statement FROM @sql_command;
EXECUTE statement;
DEALLOCATE PREPARE statement;

很遗憾,您不能仅使用MySQL语句(即插入表或与其他结果集联接)来进一步处理结果集。 因此,如果需要进行比较,最终将需要使用您喜欢的编程语言(或使用功能强大的软件)使用其他代码来完成任务。

答案 4 :(得分:0)

问题并未说明使用shell脚本来完成任务是不允许的,所以我在这里发布一个这样的方法(PHP能够调用shell脚本 - 请参阅http://php.net/manual/en/function.shell-exec.php - 如果安全模式未启用):

如果您的脚本可以使用shell访问权限和校验和工具(如md5sum) - 也可以执行类似这样的操作来收集每个表的校验和:

#!/bin/bash
DATABASEPATH="/var/lib/mysql/yourdatabase"
cd "$DATABASEPATH" &&
for TABLEFILE in `ls -t *.ibd`; do
  SUMANDTABLE=`md5sum "$TABLEFILE"`
  echo "${SUMANDTABLE//.ibd}"
done

并且可选地,如果您不想为所有表计算校验和,您还可以检查"$TABLEFILE"的修改日期是否在范围内。如果没有,您只需退出脚本(修改日期为ls -t订单,降序)。

要访问修改日期,请使用例如stat -c %Y "$TABLEFILE"。这将为您提供自Epoch以来的修改日期。

要访问当前日期,也请使用Epoch后的秒数:date +%s

然后可以从当前日期中减去修改日期,以确定"$TABLEFILE"已经改变了多少秒。

在某些情况下可以应用的另一种相关方法是保存ls -t *.ibd列表(甚至不计算校验和,只按顺序存储文件名),然后启动操作并在该操作结束时检查与另一次执行ls -t *.ibd的文件列表不同。