[英]MySQL checksum to all tables in a database
我正在评估基于 PHP/MySQL 的软件。 我想查看触发某些操作时哪些表受到影响。
在谷歌搜索之后,我被告知checksum table tbl_name
可以完成这项工作。 我只需要知道如何对数据库中的所有表使用checksum
。
由于数据库包含数百个表,因此手动对所有表进行checksum
绝对不是首选。
对所有表进行校验和检查似乎是很多昂贵的计算工作,只是为了检测哪些表发生了变化。
我建议使用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 模式预先安装在 MySQL 5.7 中。
如果您使用 MySQL 5.6,您可能需要自行安装。 它只是一个 SQL 脚本,用于在 performance_schema 中创建一些视图。 非常容易安装。
您可以在此处获取 sys 架构: https : //github.com/mysql/mysql-sys
您可以为所有表生成CHECKSUM
语句:
SELECT CONCAT('CHECKSUM TABLE ', table_name, ';') AS statement
FROM information_schema.tables
WHERE table_schema = 'YourDBNameHere'
然后复制此输出并将其粘贴到 Workbench 或您需要使用的任何工具中。 如果您需要从应用程序(例如 PHP)代码中执行此操作,那么您可能必须使用纯动态 MySQL。
我想查看触发某些操作时哪些表受到影响。
你这是什么意思?
您是否知道触发了哪些操作,而您只是想了解它们对您的数据库产生了什么影响(例如,验证它们的正确性)? 或者您不知道触发了哪些操作(例如在某个时间间隔内),但您仍然想了解数据库是如何更改的,也许是为了确定这些操作是什么?
在极少数情况下,我希望最好的方法是您正在探索的方法(检查数据库的更改)。 相反,某种形式的日志-无论是内置的RDBMS(如MySQL的通用查询日志或者是通过触发器由Sumesh建议)在(进行访问的应用程序中如)一些更高级别,或者更可能-would几乎总是更可取。 这使我倾向于认为您有XY 问题。
但是,假设您确实希望识别自上次已知的某个时间点以来已被修改的表,您可以查询INFORMATION_SCHEMA.TABLES
表,该表不仅包含 RDBMS 中每个表的CHECKSUM
,还包含其他可能有用的信息,如UPDATE_TIME
。 因此,例如,要识别在过去五分钟内更改的所有表,可以执行以下操作:
SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE UPDATE_TIME > NOW() - INTERVAL 5 MINUTE
对于那些来这里寻求答案的人来说,如何在一个查询中获取所有表的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 给出的答案的某种升级版本。
首先,我们为 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 语句对结果集进行进一步操作(即插入到表中或与其他结果集连接)。 因此,如果您需要进行一些比较,您最终将需要使用您最喜欢的编程语言(或使用功能强大的软件)中的其他代码来完成任务。
该问题并未说明不允许使用 shell 脚本来完成任务,因此我将在此处发布一种此类方法(PHP 能够调用 shell 脚本 - 请参阅http://php.net/manual/en/function.js)。 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
文件列表中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.