细心的朋友可能会发现有时候在某些库目录下有个 db.opt 文件,那这个文件是干什么用的呢?如果你用vi等编辑器打开看的话,内容很简单,是用来记录该库的默认字符集编码和字符集排序规则用的。也就是说如果你创建数据库指定默认字符集和排序规则,那么后续创建的表如果没有指定字符集和排序规则,那么该新建的表将采用db.opt文件中指定的属性。
/*
Set table default charset, if not set
SYNOPSIS
set_table_default_charset()
create_info Table create information
DESCRIPTION
If the table character set was not given explicitely,
let’s fetch the database default character set and
apply it to the table.
*/
static void set_table_default_charset(THD *thd,
HA_CREATE_INFO *create_info, char *db)
{
/*
If the table character set was not given explicitly,
let’s fetch the database default character set and
apply it to the table.
*/
if (!create_info->default_table_charset)
{
HA_CREATE_INFO db_info;
load_db_opt_by_name(thd, db, &db_info);
create_info->default_table_charset= db_info.default_table_charset;
}
}
另外要说明的是,如果你是通过alter databases(schema) 命令更改的数据库默认属性,那么现有的表的默认字符集和排序规则不受影响。
通过创建数据库指定数据库的默认字符集和排序规则:
CREATE {DATABASE | SCHEMA
} [IF NOT EXISTS] db_name
[create_specification
] …
create_specification:
[DEFAULT] CHARACTER SET [=] charset_name
| [DEFAULT] COLLATE [=] collation_name
也可以通过alter database修改
ALTER {DATABASE | SCHEMA
} [db_name
]
alter_specification …
ALTER {DATABASE | SCHEMA
} db_name
UPGRADE
DATA DIRECTORY NAME
alter_specification:
[DEFAULT] CHARACTER SET [=] charset_name
| [DEFAULT] COLLATE [=] collation_name
谭俊青 MySQL
MySQL Cluster ndb 引擎每行存储的实际长度最大为8052个字节。Blob和Text字段在ndb engine中只存储前面的256个字节。超过256自己部分存储在另外的隐藏表里面。根据字段类型,隐藏表分3种大小(chunk size)。
- Blob/Text 2000B
- MediumBlob/MediumText 4000B
- LongBlob/LongText 8000B
假如一个LongBlob字段是10,000个字节,那么需要2个chunk,第一个存储8000字节,另外一个存储剩下的2000字节。
因此为了提高效率,如果我们存储的字段在8k(约)以内,那么在不超过8052字节限制的情况下,可以考虑用varbinary存储。比如比较典型的应用 session 管理。
谭俊青 MySQL
MySQL5.1开始支持表分区,但是是水平分区,包括hash, list, range 等。
例如分区前:
| id | title | description | author |
+—-+———+————-+——————+
| 1 | title01 | desc01 | ivan |
| 2 | title02 | desc02 | ivan |
| 3 | title03 | desc03 | ivan |
| 4 | title04 | desc04 | ivan |
| 5 | title05 | desc05 | ivan@mysqlab.net |
| 6 | title06 | desc06 | ivan@mysqlab.net |
| 7 | title07 | desc07 | ivan@mysqlab.net |
| 8 | title08 | desc08 | ivan@mysqlab.net |
+—-+———+————-+——————+
分区后:
+—-+———+————-+——–+
| id | title | description | author |
+—-+———+————-+——–+
| 1 | title01 | desc01 | ivan |
| 2 | title02 | desc02 | ivan |
| 3 | title03 | desc03 | ivan |
| 4 | title04 | desc04 | ivan |
+—-+———+————-+——–+
+—-+———+————-+——————+
| id | title | description | author |
+—-+———+————-+——————+
| 5 | title05 | desc05 | ivan@mysqlab.net |
| 6 | title06 | desc06 | ivan@mysqlab.net |
| 7 | title07 | desc07 | ivan@mysqlab.net |
| 8 | title08 | desc08 | ivan@mysqlab.net |
+—-+———+————-+——————+
VP存储引擎(vertical partitioning storage engine)支持垂直分区,将不同的表根据主键作join,而且还支持不同存储引擎的表,甚至原有的表还可以带有水平分区。
详情请参考:https://launchpad.net/vpformysql
谭俊青 MySQL
这几天在中国移动音乐基地(四川成都)这儿培训MySQL Developer课程,当中萌生了个想法,采用提问的方式,然后筛选出合适的命题做介绍。
比如:MySQL是如何使用内存和磁盘的?
呵呵,被骗进来的朋友别生气,今天实在是太晚了,明早还要去上课,明后天补上。
这篇是普及MySQL基本知识的,介绍MySQL是如何使用磁盘和内存的,从手册上可以找到。
磁盘空间的占用:
- 每个数据库对应MySQL数据目录下的一个目录,不管你是采用什么存储引擎。
- 每张数据表都在其对应的数据库目录下有一个table_name.frm文件,存储的是表定义信息,有64KB的限制。
- MyISAM引擎表在其数据库目录下对应3个文件,包括上面的frm文件,还有数据文件和目录文件。
- Innodb有自己的表空间和redo日志文件。
- MySQL还有自己的日志文件,包括error log, binary log, general log等。
- 触发器存储在对应的数据库目录下。
- 认证信息存储在MySQL系统表里,在mysql库下。
- 另外mysqld服务器程序和其他一些客户端管理工具等也需要占用一定的磁盘空间。
内存的占用:
- 线程管理,服务器程序为了提高效率,会将一些信息存储于buffer(cache)。
- Memory(HEAP)引擎将数据存储在那种中。
- 临时表如果没有超过设定的限制会存储在内存中。
- 每个客户端连接都会使用一定的buffer空间
- 全局的Buffer和Cache(比如MyISAM的keybuffer,InnoDB的buffer pool, Query cache等 )
谭俊青 MySQL

最近一直在学习研究MySQL Cluster,今天正好也看到消息说支付宝在测试IBM DB2 Cluster,16个数据居节点,1个管理节点,采用万兆网卡连接。DB2 Cluster跟MySQL Cluster采用同样的share-nothing构架,网络对它来说至关重要。
但是我这里要说的是,虽然MySQL Cluster发展到今天已经取得很大的成就,性能翻了好几倍,也开始支持磁盘存储(非主键、索引),但是它有致命的弱点:不支持真正的ACID(整个机群down掉的时候,最新GCP之后提交的事务丢失),不支持在线热备(备份的时候需要停止其他请求–single user mode,防止备份数据损坏)…
话说回来,虽然缺点还不止上面提到的这些,在很多情景下不适合使用,但是不可否定它的高明。在高可用和写负载均衡上它的确是性价比很高的解决方案,比如session(Ivan)管理、用户管理等。
这几天要考试,等过阵子陆续写一些有关MySQL Cluster的文章,做下MySQL Cluster的普及和推广。
谭俊青 MySQL, MySQL Cluster, MySQL HA
MySQL5.1 引入表分区功能,使得MySQL在处理大表的能力上得到增强。使用过表分区功能的朋友应该知道,MySQL5.1中使用表分区的时候,对字段是有要求的,那就是必须是整数型,或者可以将其他类型的字段通过函数转换成整数型才可以。
/* with MySQL 5.1 ivan @ MySQL实验室(mysqlab.net/blog/) */
CREATE TABLE mysqlab_net
(
ivan DATE
)
PARTITION
BY RANGE
(TO_DAYS
(ivan
))
(
PARTITION p01
VALUES LESS THAN
(TO_DAYS
(‘2007-08-08′)),
PARTITION p02
VALUES LESS THAN
(TO_DAYS
(‘2008-08-08′)),
PARTITION p03
VALUES LESS THAN
(TO_DAYS
(‘2009-08-08′)),
PARTITION p04
VALUES LESS THAN
(MAXVALUE
));
SHOW CREATE TABLE mysqlab_net\G
*************************** 1. row ***************************
TABLE: mysqlab_net
CREATE TABLE: CREATE TABLE `mysqlab_net` (
`ivan` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (TO_DAYS(ivan))
(PARTITION p01 VALUES LESS THAN (733261) ENGINE = InnoDB,
PARTITION p02 VALUES LESS THAN (733627) ENGINE = InnoDB,
PARTITION p03 VALUES LESS THAN (733992) ENGINE = InnoDB,
PARTITION p04 VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
怎么样?读取的时候谁知道那个数字是多少?(不过也可以通过自定义函数实现还原)
MySQL5.5中加入了columns关键字,使得可读性好多了。看例子
/* with MySQL 5.5 ivan @ MySQL实验室(mysqlab.net/blog/) */
CREATE TABLE `mysqlab.net`
(
ivan DATE
)
PARTITION
BY RANGE
COLUMNS(ivan
)
(
PARTITION p01
VALUES LESS THAN
(‘2007-08-08′),
PARTITION p02
VALUES LESS THAN
(‘2008-08-08′),
PARTITION p03
VALUES LESS THAN
(‘2009-08-08′),
PARTITION p04
VALUES LESS THAN
(MAXVALUE
);
SHOW CREATE TABLE `mysqlab.net`\G
*************************** 1. row ***************************
TABLE: mysqlab.net
CREATE TABLE: CREATE TABLE `mysqlab.net` (
`ivan` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50500 PARTITION BY RANGE COLUMNS(ivan)
(PARTITION p01 VALUES LESS THAN (’2007-08-08′) ENGINE = InnoDB,
PARTITION p02 VALUES LESS THAN (’2008-08-08′) ENGINE = InnoDB,
PARTITION p03 VALUES LESS THAN (’2009-08-08′) ENGINE = InnoDB,
PARTITION p04 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB) */
另外MySQL5.5表分区(partition) columns关键字还支持多字段,比如 partition by range columns(a,b);将支持清空指定的分区TRUNCATE PARTITION。MySQL5.5有望在明年(2010)夏季GA。另外MySQL5.5支持的半同步功能在高可用上的使用,让人非常期待!
Reference: MySQL 5.5 partitioning enhancements
Note:在使用表分区的时候,并不是分区越多越好,要根据情况而定,因为会出现意想不到的问题。
谭俊青 MySQL Partition
MySQL 5.5第一个版本释出,基于MySQL5.4,性能相对于当前MySQL5.0、5.1有很大的提升,更让人可喜的是MySQL5.5内置了Google的半同步(semi-sync-replication)补丁,以此可以搭建一个相对来说比较完美的MySQL高可用方案,之前我已经在“MySQL新版(5.x)及特性”中提到过,很是让人期待!

MySQL半同步流程设计图
半同步的配置很简单:
master > INSTALL PLUGIN rpl_semi_sync_master SONAME ‘libsemisync_master.so’;
slave-x > INSTALL PLUGIN rpl_semi_sync_slave SONAME ‘libsemisync_slave.so’;
master > SET GLOBAL rpl_semi_sync_master_enabled=1;
slave-x > SET GLOBAL rpl_semi_sync_slave_enabled=1;
对于半同步需要说明的是:
1:不需要所有的slave都确认接收到复制事件
2:slave确认并不是表示执行完成
3:如果slave没有跟上同步设置将被中断继续原来的异步模式直到跟上再重新开启
注意:当前MySQL5.4, MySQL5.5都还不是GA版本,生产环境请慎重选择,升级前也请备份好数据。
谭俊青 MySQL HA, MySQL Replication
MySQL 5.1.42 预计在今年(2009)12月18日发布,其中会包含最新的Innodb Plugin。新的InnoDB Plugin在除了支持Data compression和Fast index create特性之外,兼容之前的表空间,并加入了大量Google的patch,极大的提高了Innodb的性能。
MySQL 5.4 GA 预计可能在明年夏季,roadmap如下图:

MySQL 5.5 会加入Google semi-replication patch,Google原链接。
MySQL Cluster Manager 加入自动管理功能,不过应该会收费。
———————————————-
这几天去fetion看了他们的DB,服务器奢侈(可能穷惯了),性能也很强劲30k+的QPS。不过构架有些问题,以后我想应该会改;另外还去了现场帮客户解决问题。至此来北京的计划全部打乱。下次一定提前安排,组织一次MySQL实验室聚会。
谭俊青 MySQL Cluster, MySQL Innodb, MySQL Replication, news / tools

上面是Gearman的一个角色功能图,它在整个系统体系里面担任中间代理人的作用,负责接收和分配任务并返回结果。这样它能很好的胶合各个子系统从而实现项目目标。
之所以介绍这个,我是想将它用到MySQL的监控管理备份平台上,DB服务器上运行worker daemon连接到管理节点上,这样需要对DB进行动作的时候,只要在管理节点上通过gearman下达任务即可,而且不同的地方可以用最合适的语言去实现,实现开发效率和运行效率的平衡和统一。开发人员能给我们带来这么好的东东,实乃大幸。Gearman可用的地方非常多,它在一定程度上开阔了人的思路,提供了一个相对通用的解决方案。
---------- ---------- ---------- ----------
| Client | | Client | | Client | | Client |
---------- ---------- ---------- ----------
\ / \ /
\ / \ /
-------------- --------------
| Job Server | | Job Server |
-------------- --------------
| |
----------------------------------------------
| | | |
---------- ---------- ---------- ----------
| Worker | | Worker | | Worker | | Worker |
---------- ---------- ---------- ----------
Gearman的官方网站在这里
谭俊青 C, MySQL, news / tools
前段时间看innodb plugin源码的时候,看到有如下一段
include/univ.i
/* The 2-logarithm of UNIV_PAGE_SIZE: */
#define UNIV_PAGE_SIZE_SHIFT 14
/* The universal page size of the database */
#define UNIV_PAGE_SIZE (1 << UNIV_PAGE_SIZE_SHIFT)
/* Maximum number of parallel threads in a parallelized operation */
#define UNIV_MAX_PARALLELISM 32
尝试将 UNIV_PAGE_SIZE_SHIFT 改成13 (相当于page size为8K),编译通过并可以正常使用。
后来找到Google的MySQL团队发表的一篇文章,文中的介绍 Innodb page size 可以选择 8K、 16K、 32K、 64K。不过因为Innodb每个page都有不小的冗余空间,从空间和内存利用的角度来讲,page size越大越好。但是从checkpoint的角度来讲恰恰相反,page size越小,性能越好(上次演讲的时候我介绍过原理)。所以最后选择多大的page size可以根据实际的业务测试而定。
谭俊青 C, MySQL Innodb
昨天(2009-9-9)参加了sun的培训日活动,一到会场我就后悔了,因为我没想到会议有那么正式,而我穿着有点不修边幅… 活动是成功的,因为我以为周三可能去的人不会太多,想不到会场会满座,虽然有比较浓重的广告味道,也不乏技术交流的气氛。我讲的主题是 《Innodb Optimization How and Why》,从原理上剖析innodb的性能及优化,怎么优化,为什么要这么优化。随后Q/A环节大家都很活跃,由于时间问题没能回答所有朋友的问题,如果有什么疑问可以发我email或者qq,msn交流,我很乐意跟大家讨论。 PPT下载。

2009-09-09 Sun MySQL Day Q&A 现场
谭俊青 MySQL 活动
InnoDB Plugin 1.0.4 这次加入了不少第三方的代码,个人比较在意的是 Google 和 Percona 提供的部分。Innodb从而实现了性能上很大的提升,不想以前在并发稍大(比如>8),吞吐量升值会下将,现在却又很大的提升。
个人关注的改进部分有:
1: Multiple Background Threads
最初由Google提供的补丁,参数 innodb_file_io_threads 可以设置io threads的数量,之前是假的…
2:Master Thread I/O Capacity Tuning
之前innodb在代码里面写死了 innodb_io_capacity 为100,但是现在db服务器很多都是用多块硬盘做raid10,IOPS 一般都远不止100,因此这次改进之后 innodb_io_capacity 变成可以动态调整的参数,用于DBA选择一个合适的值。
3:Group Commit
这个据说以前4.x之前就支持的,现在又回来了,支持多个事务同时提交(主要是redo log,之前是因为binlog的2-phase commit protocal的原因中止的),从而提高吞吐量。
4:Adaptive Flushing
这个非常有用,大家知道在脏数据到达设置的阀值比例之后,会开始主动做checkpoint,当checkpoint无可避免的时候,这时候会堵塞用户线程,从而出现性能的突然下降。现在这个问题得到巧妙的解决,会根据算法动态的调整checkpoint的速率,避免出现性能的突然降低。
REFERENCE:
http://www.innodb.com/wp/2009/08/11/innodb-plugin-104-released/
http://www.innodb.com/wp/products/innodb_plugin/license/third-party-contributions-in-innodb-plugin-1-0-4/
谭俊青 MySQL, MySQL Innodb
Yasufumi 提供了一个用户在innodb crash后快速恢复的补丁
如果最后该补丁能够纳入官方体系,那么Innodb将在性能上又有很大的提升。
上次MySQL中文实验室的聚会中介绍了buffer大小,redo log大小,checkpoint对性能的影响。那么如果大的redo log能在crash后快速回复的话,我们可以将redo log设置到最大,这样可以尽可能降低checkpoint的次数,来提升数据库的性能。
再者还可以将redo log 4G的限制从源码上解决,从而适应现在动则上10G的buffer。
谭俊青 MySQL Innodb
最近评论