Documentation Home
MySQL 8.0 参考手册  / 第 15 章 InnoDB 存储引擎  / 15.20 InnoDB 内存缓存插件  / 15.20.6 为 InnoDB memcached 插件编写应用程序  /  14.21.5.1 为 InnoDB memcached 插件调整现有的 MySQL 模式

14.21.5.1 为 InnoDB memcached 插件调整现有的 MySQL 模式

在调整现有 MySQL 模式或应用程序以使用 插件 时,请考虑memcached应用程序 的这些方面:daemon_memcached

  • memcached键不能包含空格或换行符,因为这些字符在 ASCII 协议中用作分隔符。如果您使用包含空格的查找值,请将它们转换或散列为不带空格的值,然后再将它们用作调用 add()set()get()等的键。虽然理论上这些字符在使用二进制协议的程序的键中是允许的,但您应该限制键中使用的字符以确保与广泛的客户端兼容。

  • 如果表中有一个短数字 主键列,通过将整数转换为字符串值将其InnoDB用作memcached的唯一查找键。如果 memcached服务器用于多个应用程序,或者有多个 InnoDB表,请考虑修改名称以确保其唯一性。例如,在数值前加上表名或数据库名和表名。

    笔记

    daemon_memcached插件支持插入和读取已定义为主键 InnoDB 的映射表。INTEGER

  • 您不能将分区表用于使用memcached查询或存储的数据。

  • memcached协议 将数值作为字符串传递。要在基础表中存储数值InnoDB,以实现可在 SQL 函数(例如 SUM()or )中使用的计数器,AVG()例如:

    • 使用VARCHAR具有足够字符的列来容纳最大预期数字的所有数字(如果适用于负号、小数点或两者,还可以使用其他字符)。

    • 在任何使用列值执行算术的查询中,使用该CAST()函数将值从字符串转换为整数,或转换为其他一些数字类型。例如:

      # Alphabetic entries are returned as zero.
      
      SELECT CAST(c2 as unsigned integer) FROM demo_test;
      
      # Since there could be numeric values of 0, can't disqualify them.
      # Test the string values to find the ones that are integers, and average only those.
      
      SELECT AVG(cast(c2 as unsigned integer)) FROM demo_test
        WHERE c2 BETWEEN '0' and '9999999999';
      
      # Views let you hide the complexity of queries. The results are already converted;
      # no need to repeat conversion functions and WHERE clauses each time.
      
      CREATE VIEW numbers AS SELECT c1 KEY, CAST(c2 AS UNSIGNED INTEGER) val
        FROM demo_test WHERE c2 BETWEEN '0' and '9999999999';
      SELECT SUM(val) FROM numbers;
      笔记

      通过调用 将结果集中的任何字母值转换为 0 CAST()AVG()使用取决于结果集中行数的函数(例如 )时,请包含WHERE子句以过滤掉非数字值。

  • 如果InnoDB用作键的列的值可能超过 250 个字节,则将值散列为小于 250 个字节。

  • 要将现有表与 daemon_memcached插件一起使用,请在表中为其定义一个条目innodb_memcache.containers 。要使该表成为所有 memcacheddefault请求的默认表,请在列中指定一个值 name ,然后重新启动 MySQL 服务器以使更改生效。如果您为不同类别的memcachedinnodb_memcache.containers数据使用多个表,请在表中使用您选择的 值设置多个条目 ,然后以或 的形式 name发出 memcached请求get @@nameset @@name 在应用程序中指定要用于后续memcached请求的表。

    有关使用预定义表以外的表的 示例test.demo_test,请参阅 示例 14.13,“将您自己的表与 InnoDB memcached 应用程序一起使用”。对于所需的表布局,请参阅 第 14.21.7 节,“InnoDB memcached 插件内部”

  • 要将多个InnoDB表列值与memcached键值对一起使用,请在表 条目的value_columns 字段中指定以逗号、分号、空格或竖线字符分隔的列名。例如,在 字段 中指定或 。innodb_memcache.containersInnoDBcol1,col2,col3col1|col2|col3value_columns

    在将字符串传递给memcached addset调用 之前,使用竖线字符作为分隔符将列值连接成单个字符串 。该字符串会自动解压缩到正确的列中。每次 get调用都会返回一个包含列值的字符串,该列值也由竖线字符分隔。您可以使用适当的应用程序语言语法解压这些值。

示例 14.13 在 InnoDB memcached 应用程序中使用您自己的表

此示例说明如何将您自己的表与memcached用于数据操作的示例 Python 应用程序一起使用。

该示例假定 daemon_memcached已按照第 14.21.3 节“设置 InnoDB memcached 插件”中的说明安装插件。它还假设您的系统配置为运行使用该python-memcache模块的 Python 脚本。

  1. 创建multicol存储国家信息的表,包括人口、面积和驾驶员侧数据('R'右侧和 'L'左侧)。

    mysql> USE test;
    
    mysql> CREATE TABLE `multicol` (
            `country` varchar(128) NOT NULL DEFAULT '',
            `population` varchar(10) DEFAULT NULL,
            `area_sq_km` varchar(9) DEFAULT NULL,
            `drive_side` varchar(1) DEFAULT NULL,
            `c3` int(11) DEFAULT NULL,
            `c4` bigint(20) unsigned DEFAULT NULL,
            `c5` int(11) DEFAULT NULL,
            PRIMARY KEY (`country`)
            ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  2. 向表中插入一条记录, innodb_memcache.containers以便daemon_memcached插件可以访问该multicol表。

    mysql> INSERT INTO innodb_memcache.containers
           (name,db_schema,db_table,key_columns,value_columns,flags,cas_column,
           expire_time_column,unique_idx_name_on_key)
           VALUES
           ('bbb','test','multicol','country','population,area_sq_km,drive_side',
           'c3','c4','c5','PRIMARY');
    
    mysql> COMMIT;
    • 表的innodb_memcache.containers 记录multicol指定name'bbb',这是表标识符。

      笔记

      如果单个InnoDB表用于所有memcached应用程序,该name值可以设置 default为避免使用 @@符号切换表。

    • db_schema列设置为 test,这是multicol表所在的数据库的名称。

    • db_table列设置为 multicol,这是 InnoDB表的名称。

    • key_columns设置为唯一 country列。该 列在表定义 country中被定义为主键。multicol

    • 数据不是由单个InnoDB表列来保存复合数据值,而是分为三个表列(populationarea_sq_kmdrive_side)。value_columns为了容纳多个值列,在该字段中指定了一个以逗号分隔的列列表 。字段中定义的value_columns列是存储或检索值时使用的列。

    • flagsexpire_time和 字段的 值cas_column基于demo.test示例表中使用的值。这些字段在使用该插件的应用程序中通常并不重要, daemon_memcached因为 MySQL 保持数据同步,并且无需担心数据过期或变得陈旧。

    • unique_idx_name_on_key字段设置为PRIMARY,它指的 country是表中唯一列 上定义的主索引multicol

  3. 将示例 Python 应用程序复制到一个文件中。在此示例中,示例脚本被复制到一个名为 multicol.py.

    示例 Python 应用程序将数据插入 multicol表中并检索所有键的数据,演示如何 通过插件 访问InnoDB表 。daemon_memcached

    import sys, os
    import memcache
    
    def connect_to_memcached():
      memc = memcache.Client(['127.0.0.1:11211'], debug=0);
      print "Connected to memcached."
      return memc
    
    def banner(message):
      print
      print "=" * len(message)
      print message
      print "=" * len(message)
    
    country_data = [
    ("Canada","34820000","9984670","R"),
    ("USA","314242000","9826675","R"),
    ("Ireland","6399152","84421","L"),
    ("UK","62262000","243610","L"),
    ("Mexico","113910608","1972550","R"),
    ("Denmark","5543453","43094","R"),
    ("Norway","5002942","385252","R"),
    ("UAE","8264070","83600","R"),
    ("India","1210193422","3287263","L"),
    ("China","1347350000","9640821","R"),
    ]
    
    def switch_table(memc,table):
      key = "@@" + table
      print "Switching default table to '" + table + "' by issuing GET for '" + key + "'."
      result = memc.get(key)
    
    def insert_country_data(memc):
      banner("Inserting initial data via memcached interface")
      for item in country_data:
        country = item[0]
        population = item[1]
        area = item[2]
        drive_side = item[3]
    
        key = country
        value = "|".join([population,area,drive_side])
        print "Key = " + key
        print "Value = " + value
    
        if memc.add(key,value):
          print "Added new key, value pair."
        else:
          print "Updating value for existing key."
          memc.set(key,value)
    
    def query_country_data(memc):
      banner("Retrieving data for all keys (country names)")
      for item in country_data:
        key = item[0]
        result = memc.get(key)
        print "Here is the result retrieved from the database for key " + key + ":"
        print result
        (m_population, m_area, m_drive_side) = result.split("|")
        print "Unpacked population value: " + m_population
        print "Unpacked area value      : " + m_area
        print "Unpacked drive side value: " + m_drive_side
    
    if __name__ == '__main__':
    
      memc = connect_to_memcached()
      switch_table(memc,"bbb")
      insert_country_data(memc)
      query_country_data(memc)
    
      sys.exit(0)

    示例 Python 应用说明:

    • 运行应用程序不需要数据库授权,因为数据操作是通过memcached接口执行的。唯一需要的信息是 memcached守护程序侦听的本地系统上的端口号。

    • 为确保应用程序使用该 multicol表,将调用该 函数,该函数使用符号switch_table()执行虚拟getset请求 。@@请求中的 name值为 bbb,即 字段multicol中定义的表标识 innodb_memcache.containers.name

      name在实际应用程序中可能会使用 更具描述性的值。get @@...此示例仅说明在请求 中指定了表标识符而不是表名。

    • 用于插入和查询数据的实用函数演示了如何将 Python 数据结构转换为管道分隔值,以便使用 addset 请求将数据发送到 MySQL,以及如何解压缩get请求返回的管道分隔值。只有在将单个memcached值映射到多个 MySQL 表列 时才需要进行此额外处理。

  4. 运行示例 Python 应用程序。

    $> python multicol.py

    如果成功,示例应用程序将返回以下输出:

    Connected to memcached.
    Switching default table to 'bbb' by issuing GET for '@@bbb'.
    
    ==============================================
    Inserting initial data via memcached interface
    ==============================================
    Key = Canada
    Value = 34820000|9984670|R
    Added new key, value pair.
    Key = USA
    Value = 314242000|9826675|R
    Added new key, value pair.
    Key = Ireland
    Value = 6399152|84421|L
    Added new key, value pair.
    Key = UK
    Value = 62262000|243610|L
    Added new key, value pair.
    Key = Mexico
    Value = 113910608|1972550|R
    Added new key, value pair.
    Key = Denmark
    Value = 5543453|43094|R
    Added new key, value pair.
    Key = Norway
    Value = 5002942|385252|R
    Added new key, value pair.
    Key = UAE
    Value = 8264070|83600|R
    Added new key, value pair.
    Key = India
    Value = 1210193422|3287263|L
    Added new key, value pair.
    Key = China
    Value = 1347350000|9640821|R
    Added new key, value pair.
    
    ============================================
    Retrieving data for all keys (country names)
    ============================================
    Here is the result retrieved from the database for key Canada:
    34820000|9984670|R
    Unpacked population value: 34820000
    Unpacked area value      : 9984670
    Unpacked drive side value: R
    Here is the result retrieved from the database for key USA:
    314242000|9826675|R
    Unpacked population value: 314242000
    Unpacked area value      : 9826675
    Unpacked drive side value: R
    Here is the result retrieved from the database for key Ireland:
    6399152|84421|L
    Unpacked population value: 6399152
    Unpacked area value      : 84421
    Unpacked drive side value: L
    Here is the result retrieved from the database for key UK:
    62262000|243610|L
    Unpacked population value: 62262000
    Unpacked area value      : 243610
    Unpacked drive side value: L
    Here is the result retrieved from the database for key Mexico:
    113910608|1972550|R
    Unpacked population value: 113910608
    Unpacked area value      : 1972550
    Unpacked drive side value: R
    Here is the result retrieved from the database for key Denmark:
    5543453|43094|R
    Unpacked population value: 5543453
    Unpacked area value      : 43094
    Unpacked drive side value: R
    Here is the result retrieved from the database for key Norway:
    5002942|385252|R
    Unpacked population value: 5002942
    Unpacked area value      : 385252
    Unpacked drive side value: R
    Here is the result retrieved from the database for key UAE:
    8264070|83600|R
    Unpacked population value: 8264070
    Unpacked area value      : 83600
    Unpacked drive side value: R
    Here is the result retrieved from the database for key India:
    1210193422|3287263|L
    Unpacked population value: 1210193422
    Unpacked area value      : 3287263
    Unpacked drive side value: L
    Here is the result retrieved from the database for key China:
    1347350000|9640821|R
    Unpacked population value: 1347350000
    Unpacked area value      : 9640821
    Unpacked drive side value: R
  5. 查询该innodb_memcache.containers 表以查看您之前为该 multicol表插入的记录。第一条记录是demo_test在初始 daemon_memcached插件设置期间创建的表的样本条目。第二条记录是您为表插入的条目 multicol

    mysql> SELECT * FROM innodb_memcache.containers\G
    *************************** 1. row ***************************
                      name: aaa
                 db_schema: test
                  db_table: demo_test
               key_columns: c1
             value_columns: c2
                     flags: c3
                cas_column: c4
        expire_time_column: c5
    unique_idx_name_on_key: PRIMARY
    *************************** 2. row ***************************
                      name: bbb
                 db_schema: test
                  db_table: multicol
               key_columns: country
             value_columns: population,area_sq_km,drive_side
                     flags: c3
                cas_column: c4
        expire_time_column: c5
    unique_idx_name_on_key: PRIMARY
  6. 查询multicol表以查看示例 Python 应用程序插入的数据。数据可用于 MySQL 查询,它演示了如何使用 SQL 或通过应用程序(使用适当的 MySQL 连接器或 API)访问相同的数据。

    mysql> SELECT * FROM test.multicol;
    +---------+------------+------------+------------+------+------+------+
    | country | population | area_sq_km | drive_side | c3   | c4   | c5   |
    +---------+------------+------------+------------+------+------+------+
    | Canada  | 34820000   | 9984670    | R          |    0 |   11 |    0 |
    | China   | 1347350000 | 9640821    | R          |    0 |   20 |    0 |
    | Denmark | 5543453    | 43094      | R          |    0 |   16 |    0 |
    | India   | 1210193422 | 3287263    | L          |    0 |   19 |    0 |
    | Ireland | 6399152    | 84421      | L          |    0 |   13 |    0 |
    | Mexico  | 113910608  | 1972550    | R          |    0 |   15 |    0 |
    | Norway  | 5002942    | 385252     | R          |    0 |   17 |    0 |
    | UAE     | 8264070    | 83600      | R          |    0 |   18 |    0 |
    | UK      | 62262000   | 243610     | L          |    0 |   14 |    0 |
    | USA     | 314242000  | 9826675    | R          |    0 |   12 |    0 |
    +---------+------------+------------+------------+------+------+------+
    笔记

    在定义被视为数字的列的长度时,始终允许足够的大小来容纳必要的数字、小数点、符号字符、前导零等。字符串列中的太长值(例如 a VARCHAR)会通过删除一些字符来截断,这可能会产生无意义的数值。

  7. 或者,对存储memcached数据 的InnoDB表 运行报告类型的查询 。

    您可以通过 SQL 查询生成报告,跨任何列执行计算和测试,而不仅仅是 country键列。(因为以下示例仅使用少数几个国家/地区的数据,所以数字仅供说明之用。)以下查询返回人们靠右行驶的国家/地区的平均人口,以及名称以U ”开头的国家/地区的平均面积”

    mysql> SELECT AVG(population) FROM multicol WHERE drive_side = 'R';
    +-------------------+
    | avg(population)   |
    +-------------------+
    | 261304724.7142857 |
    +-------------------+
    
    mysql> SELECT SUM(area_sq_km) FROM multicol WHERE country LIKE 'U%';
    +-----------------+
    | sum(area_sq_km) |
    +-----------------+
    |        10153885 |
    +-----------------+

    因为populationand area_sq_km列存储字符数据而不是强类型数字数据,所以函数(例如 AVG()and SUM())首先将每个值转换为数字。这种方法 不适用于 <or之类的运算符>,例如,在比较基于字符的值时9 > 1000,这是子句中所不期望的,例如ORDER BY population DESC. 要获得最准确的类型处理,请针对将数字列转换为适当类型的视图执行查询。这种技术可以让你发出简单的SELECT *来自数据库应用程序的查询,同时确保转换、过滤和排序是正确的。以下示例显示了一个视图,可以查询该视图以按人口降序查找前三个国家,结果反映multicol表中的最新数据,并将人口和面积数字视为数字:

    mysql> CREATE VIEW populous_countries AS
           SELECT
           country,
           cast(population as unsigned integer) population,
           cast(area_sq_km as unsigned integer) area_sq_km,
           drive_side FROM multicol
           ORDER BY CAST(population as unsigned integer) DESC
           LIMIT 3;
    
    mysql> SELECT * FROM populous_countries;
    +---------+------------+------------+------------+
    | country | population | area_sq_km | drive_side |
    +---------+------------+------------+------------+
    | China   | 1347350000 |    9640821 | R          |
    | India   | 1210193422 |    3287263 | L          |
    | USA     |  314242000 |    9826675 | R          |
    +---------+------------+------------+------------+
    
    mysql> DESC populous_countries;
    +------------+---------------------+------+-----+---------+-------+
    | Field      | Type                | Null | Key | Default | Extra |
    +------------+---------------------+------+-----+---------+-------+
    | country    | varchar(128)        | NO   |     |         |       |
    | population | bigint(10) unsigned | YES  |     | NULL    |       |
    | area_sq_km | int(9) unsigned     | YES  |     | NULL    |       |
    | drive_side | varchar(1)          | YES  |     | NULL    |       |
    +------------+---------------------+------+-----+---------+-------+