1

我有一个 PHP 应用程序,它为多个用户使用单个数据库。用户登录后,他们的 ID 存储在会话中,他们使用应用程序检索或更新数据库中的数据。

出于安全/存档的目的,我想以每个用户为基础记录每个 SQL 事务。请注意,“用户”不是 MySQL 用户,因为他们只使用一个用户。我该怎么做呢?

我目前正在运行 Centos 5.8、PHP 5.3.18 和 MySQL 5.5。

谢谢

4

3 回答 3

0

您可以配置 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'
于 2013-04-04T13:13:41.797 回答
0

您可以打开并阅读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);

将此值存储到某个位置以在日志中匹配。

于 2013-04-04T13:30:30.913 回答
0
$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:谢谢编辑:)

于 2013-04-04T13:00:49.890 回答