我有一个 PHP 应用程序,它为多个用户使用单个数据库。用户登录后,他们的 ID 存储在会话中,他们使用应用程序检索或更新数据库中的数据。
出于安全/存档的目的,我想以每个用户为基础记录每个 SQL 事务。请注意,“用户”不是 MySQL 用户,因为他们只使用一个用户。我该怎么做呢?
我目前正在运行 Centos 5.8、PHP 5.3.18 和 MySQL 5.5。
谢谢
您可以配置 MySQL 以生成通用查询日志(GQL)。此日志记录已建立的客户端连接和从所有客户端接收到的语句。它是一个常规的文本日志文件,它按照接收到的顺序记录针对您的 DBMS 的每个命令。它包含时间戳、ID、命令和参数。
IP 地址和会话不存在,因为数据库请求通过服务器在本地运行。时间戳允许与来自 Web 服务器的客户端的 IP 条目进行相当精确的匹配,即 Apache httpd 或 Tomcat访问日志文件(ALF)。
我们使用 GQL 来增强 GWT Web 应用程序产生的稀疏 ALF 信息。
此示例常规查询日志应该给您的想法:
110602 12:55:20 3 Connect root@localhost on w2p
3 Query /* mysql-connector-java-5.1.15 ( Revision: ${bzr.revision-id} ) */SHOW VARIABLES WHERE Variable_name ='language' OR Variable_name = 'net_write_timeout' OR Variable_name = 'interactive_timeout' OR Variable_name = 'wait_timeout' OR Variable_name = 'character_set_client' OR Variable_name = 'character_set_connection' OR Variable_name = 'character_set' OR Variable_name = 'character_set_server' OR Variable_name = 'tx_isolation' OR Variable_name = 'transaction_isolation' OR Variable_name = 'character_set_results' OR Variable_name = 'timezone' OR Variable_name = 'time_zone' OR Variable_name = 'system_time_zone' OR Variable_name = 'lower_case_table_names' OR Variable_name = 'max_allowed_packet' OR Variable_name = 'net_buffer_length' OR Variable_name = 'sql_mode' OR Variable_name = 'query_cache_type' OR Variable_name = 'query_cache_size' OR Variable_name = 'init_connect'
110602 12:55:21 3 Query /* mysql-connector-java-5.1.15 ( Revision: ${bzr.revision-id} ) */SELECT @@session.auto_increment_increment
3 Query SHOW COLLATION
3 Query SET NAMES utf8mb4
3 Query SET character_set_results = NULL
3 Query SET autocommit=1
3 Query select * from user where username = 'asdasd' and password = 'aa'
1 Query show global status
110602 12:55:25 1 Query show global status
110602 12:55:30 3 Query select * from user where username = 'costis' and password = 'snafu'
您可以打开并阅读MySQL 一般查询日志。它包含所有这样的查询:
...
130404 19:02:50 476 Connect test@localhost on test
476 Query SET NAMES utf8
476 Query SELECT * FROM `table1`
130404 19:02:52 476 Quit
130404 19:03:33 477 Connect test@localhost on test
477 Query SET NAMES utf8
...
476、477 等是MySQL 线程 ID。每个新连接都拥有它的 ID。您只需要知道用户的线程 id即可。对于 PHP mysqli 扩展,您可以使用mysqli_thread_id()
echo $_SESSION['username'].' '.
date('Y-m-d H:i:s').' '.
mysqli_thread_id($link);
将此值存储到某个位置以在日志中匹配。
$sql = "UPDATE table SET col = ?"
$db->prepare($sql);
//some params etc...
$filename = '/dir/logs/log-' . $_SESSION['username'] . '';
$handle = fopen($filename, "wr");
$db->execute();
fwrite($handle, $sql);
这是一个简单的示例,您如何使用查询来执行和写入以用户命名的文件。好吧,使用这种方式也许你会在执行之前得到 $sql 的内容,但我想你已经明白了。
PS:谢谢编辑:)