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

v1uwarro  于 2023-10-15  发布在  Mysql
关注(0)|答案(5)|浏览(174)

我正在评估一个基于PHP/MySQL的软件。我想看看当某些操作触发时哪些表受到影响。
经过一番谷歌搜索,我被告知checksum table tbl_name可以完成这项工作。我只需要知道如何对数据库中的所有表使用checksum
checksum所有的表一个接一个手动绝对不是首选的数据库包含数百个表。

iqih9akk

iqih9akk1#

对所有表进行校验和似乎是一项昂贵的计算工作,只是为了检测哪些表发生了变化。
我建议使用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 schema在MySQL 5.7中预装。
如果你使用MySQL 5.6,你可能需要自己安装。它只是一个SQL脚本,用于在performance_schema中创建一些视图。非常容易安装。
你可以在这里得到sys schema:https://github.com/mysql/mysql-sys

qvtsj1bj

qvtsj1bj2#

我想看看当某些操作触发时哪些表受到影响。
你这是什么意思?
您是否知道触发了哪些操作,并且您只是试图了解它们对数据库的影响(例如,以验证其正确性)。或者你不知道已经触发了什么操作(例如,但是您仍然想了解数据库是如何更改的,也许是为了确定这些操作是什么?
在很少的情况下,我会期望最好的方法是您正在探索的方法(检查数据库的更改)。相反,某种形式的 * 日志记录 *-无论是内置于RDBMS(如MySQL的General Query Log或Sumesh建议的triggers),还是更高级别(例如,在访问应用程序内)-几乎总是优选的。这让我倾向于认为你有一个XY Problem
但是,假设您确实希望识别自某个已知的最后一个良好时间点以来被修改的表,则可以查询INFORMATION_SCHEMA.TABLES表,该表不仅包含RDBMS中每个表的CHECKSUM,还包含其他潜在有用的信息,如UPDATE_TIME。因此,例如,要识别在过去五分钟内更改的所有表,可以执行以下操作:

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

avwztpqn3#

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

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

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

6jygbczu

6jygbczu4#

对于那些来这里寻求答案的人来说,如何在一个查询中获得所有表的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
);

然后我们把所有的表名放在一个KSUM 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语句进一步操作结果集(即插入到表中或与其他结果集连接)。因此,如果你需要做一些比较,你最终需要使用你最喜欢的编程语言(或使用功能强大的软件)来完成任务。

ao218c7q

ao218c7q5#

这个问题并没有说明不允许使用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"。这将给你给予修改日期,以秒为单位,自纪元。
要访问当前日期(也以自纪元以来的秒为单位),请使用:用途:date +%s
然后,可以从当前日期中减去修改日期,以确定"$TABLEFILE"在多少秒前发生了更改。
另一个相关的方法,在某些情况下可以应用,将是保存ls -t *.ibd列表(甚至不计算校验和,只是按顺序存储文件名),然后开始一个操作,并在该操作结束时检查文件列表与另一个ls -t *.ibd执行的差异。

相关问题