【问题标题】:Logging actions to the database - schema and advice - MySQL将操作记录到数据库 - 模式和建议 - MySQL
【发布时间】:2011-11-03 02:23:03
【问题描述】:

我正在考虑将所有站点/用户操作记录到数据库中,并希望对此有所了解。此日志将用于各种事情,包括限制(登录尝试等)、客户服务、一般维护等。

这样好吗?我想这取决于流量,但这会导致连续插入出现任何问题吗? (我正在考虑将 InnoDB 用于 FK 约束)

如果不是,您会建议哪种模式,以便它足够灵活以支持来自注册用户和匿名用户的不同类型的操作?

我在想这样的事情:

CREATE TABLE `logs` (
 `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
 `action` varchar(128) COLLATE utf8_bin NOT NULL,
 `user_id` bigint(20) unsigned DEFAULT NULL,
 `value` varchar(128) COLLATE utf8_bin DEFAULT NULL,
 `ip` varchar(40) COLLATE utf8_bin NOT NULL,
 `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 PRIMARY KEY (`id`),
 KEY `action` (`action`,`user_id`),
 CONSTRAINT `logs_ibfk_1` FOREIGN KEY (`action`) REFERENCES `logs_actions` (`name`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

CREATE TABLE `logs_actions` (
 `id` int(5) NOT NULL AUTO_INCREMENT,
 `name` varchar(128) COLLATE utf8_bin NOT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

这是一个好方法吗?

【问题讨论】:

  • 为什么使用 InnoDB 进行日志记录?通常使用 MISAM 进行日志记录。
  • @Dor 为什么?不要在没有正当理由的情况下放弃那块金块。 :-) 使用 MyISAM 降低资源利用率?表级锁定 (MyISAM) 会成为问题吗?等谢谢。
  • @Wiseguy:我已经发布了一个答案来解释这一点以及更多......
  • 你解决了吗?如果没有,您应该添加评论或使用更多信息编辑您的问题。

标签: mysql database logging schema database-schema


【解决方案1】:

user_id bigint(20),什么!你是 facebook 的开发者吗? ;-) 4 字节的 int 还不够吗? See MySql Numeric Types

我会将AUTO_INCREMENT 放在logs_actions 上,因为您需要将应用程序编码为特定值,因此您需要在插入时控制此值。

此外,如果您想稍微减少开销,请考虑删除 FK(至少是级联)。

【讨论】:

    【解决方案2】:

    我认为 MyIsam 或 Archive 表更适合记录日志。因为您不需要对表进行事务或并发访问。如果不打算从表中删除数据 MyIsam 将允许您进行并发插入,这样您就可以避免阻塞整个表。

    使用外键会减慢插入表的速度,因此如果您决定使用 innodb,请尽量避免使用外键。

    关于表格方案:

    要存储 ip,您应该选择 int 类型并使用 inet_aton 函数。见http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_inet-aton

    【讨论】:

      【解决方案3】:

      • 使用 MyISAM 表进行日志记录,它们启用并发 SELECT 和 INSERT 查询 - 表级锁定不会干扰这些类型的查询。
      • 在 MySQL 中,UTF-8 列每个字符需要 3 个字节,因此能够容纳 128 个 UTF-8 字符的列实际上可以存储 128*3=384 个字节,大于 256,因此这些列将有 2 个字节来计算列中的字符数,而不是 1 个字节(这可能是您所期望的)。
      • 为 ip 列使用 INT 列类型 - 将节省大量存储空间并显着缩短检索时间。
      • 尝试将文本列 action 和 value 批处理成单个列(可能命名为 queryString,代表用户在页面中的操作和价值)
      • 具有此列顺序的索引:

        KEY `action` (`action`,`user_id`)
        

        不好,应该避免,因为文本列首先出现。

      • 我建议通过这本好书学习如何优化 MySQL 的模式和查询:

        高性能 MySQL:优化、备份、复制和 更多,第二版,由 Baron Schwartz 等人撰写。版权所有 2008 O'Reilly 媒体公司,9780596101718。

      【讨论】:

        【解决方案4】:

        还要考虑以下几点:

        The TIMESTAMP data type is used for values that contain both date and time parts.
        TIMESTAMP has a range of '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC.
        

        摘自:

        http://dev.mysql.com/doc/refman/5.0/en/datetime.html

        评论:

        http://2038bug.com/

        可能需要使用 DATETIME。

        问候。

        【讨论】:

          猜你喜欢
          • 2011-05-10
          • 2011-08-20
          • 2014-06-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-17
          • 2014-09-02
          • 1970-01-01
          相关资源
          最近更新 更多