mysql内存表 redis_mysql的MEMORY引擎为什么应用没有redis的应用广泛?

论坛PunBB(FluxBB)里的online表,Discuz!里的pre_common_session等一些表都使用了MySQL内存表.

用MySQL内存表(新ENGINE=MEMORY或旧TYPE=HEAP)实现会话存储还是不错的.

CREATE TABLE online (

user_id int(10) unsigned NOT NULL,

session text NOT NULL,

md5 char(32) NOT NULL,

PRIMARY KEY (user_id)

) ENGINE=MEMORY DEFAULT CHARSET=utf8;

其中:

user_id存储的是用户的ID,作为主键.

session存储的是用户的会话数组经过serialize或json_encode后的字符串.

md5存储的是session字符串的MD5值,用于实现Check And Set版本号乐观锁:

--读取会话

SELECT session, md5 FROM online WHERE user_id = $user_id

--写入会话时需要用到这里查出来的md5(就是下面的$last_md5)

--写入会话

UPDATE online

SET session = $str, md5 = md5($str)

WHERE user_id = $user_id

AND md5 = $last_md5 --检查MD5,确保session字段没有被修改过

写入时除了要注意检查MD5,还要注意用mb_strlen检查会话字符串长度不要超过text类型字段的最大限制(21844个utf8字符,下面会提到计算方法).

用MySQL内存表实现K/V存储也可以,设置3个字段,分别为键/值/时间,比如:

CREATE TABLE mem (

k varchar(32) NOT NULL,

v text NOT NULL,

t bigint(20) unsigned NOT NULL,

PRIMARY KEY (k),

KEY (t)

) ENGINE=MEMORY DEFAULT CHARSET=utf8;

INSERT INTO mem (k, v, t) VALUES ('key1', 'value1', '20160906173140');

INSERT INTO mem (k, v, t) VALUES ('key2', 'value2', '20160906173140');

时间格式时date('YmdHis'),添加索引,用于检索.

键最长为32个字符,超过大小可以编码为MD5后存储.

值最长为floor((65535-2)/3)=21844个utf8字符,

这是因为text类型最多存储65535字节的文本字段,

存储时在内容前使用2字节表示内容的字节数.

除以3是因为一个utf8字符占用3个字节.

floor为向下取整.

要存储更大的值,可以使用mediumtext或longtext:

mediumtext: 16777215(16MB)

最多存储16777215字节的文本字段,

存储时在内容前使用3字节表示内容的字节数.

longtext: 4294967295(4GB)

最多存储4294967295字节的文本字段,

存储时在内容前使用4字节表示内容的字节数.

另外内存表大写max_heap_table_size默认16MB(执行SELECT @@max_heap_table_size;可见).

可以在my.cnf里自定义,比如设置为1G:

[mysqld]

max_heap_table_size=1G

MySQL内存表索引类型默认为HASH.

HASH索引的查询效率要高于BTREE索引.

使用Redis需要额外的服务维护成本.

虚拟主机上也无法使用Redis服务.

PHP连接Redis也需要额外的开销.

所以,MySQL内存表在Redis面前绝不是一无是处.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值