mysql是一个开放源码的小型关联式数据库管理系统,开发者为瑞典mysql ab公司。目前mysql被广泛地应用在internet上的中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低网站总体拥有成本而选择了mysql作为网站数据库。
mysql开发团队于12日宣布mysql 8.0.0开发里程碑版本(dmr)发布!可能有人会惊奇mysql为何从5.x一下跳跃到了8.0。事实上,mysql 5.x系列已经延续了很多年,从被oracle收购之前就是5.1,而收购之后一直维持在5.x,比如5.5,5.6,5.7等等。其实,如果按照原本的发布节奏,可以把5.6.x当成6.x,5.7.x当成7.x。所以,只是换了版本命名方式而已。
不过这次发布的mysql 8.0.0开发版本还是有不少亮点的。
mysql 8.0.0亮点
事务性数据字典,完全脱离了myisam存储引擎
真正将数据字典放到了innodb中的一些表中,从此不再需要frm、trg、par文件啦!information schema现在以数据字典表的一个视图出现。原则上可以完全不需要myisam数据表类型了,所有的系统表都可以放到innodb之中。
sql角色
角色是一系列权限的集合。可以创建角色,给某个用户授予和去除角色。这对于权限管理很方便。
utf8mb4字符集将成为默认字符集,并支持unicode 9
默认字符集将从 latin1 改为 utf8mb4,默认定序collation将从latin1_swedish_ci 改为 utf8mb4_800_ci_ai。
不可见索引
可以将一些索引设置为不可见,这样sql优化器就不会用到它,但是它会继续在后台保持更新。当有需要时,可以随时恢复可见。
对二进制数据可以进行位操作
不仅仅可以对 bigint进行位操作,从8.0开始也支持对 [var]binary/[tiny|medium|long]blob进行位操作了。
改进了对ipv6和uuid的操作
inet6_aton() 和 inet6_ntoa() 现在可以进行位操作了,因为inet6_aton()现在返回的是varbinary(16) 数据类型(128位)。改进了uuid操作,引入了三个新的函数 uuid_to_bin(), bin_to_uuid()和 is_uuid() 。mysql并没有特殊的ipv6和uuid数据类型,而是以varbinary(16) 数据类型保存的。
持续性的全局变量
可以用 set persist 来设置持久性的全局变量,即便服务器重启也会保持下来。
性能数据库performance schema的改进
比如对性能数据库增加了100多个索引,可以检索更快。
重构sql分析器
持续不断的逐步改进sql分析器。旧的分析器由于其语法复杂性和自顶向下的分析方式从而有严重的限制,导致难以维护和扩展。
成本模型
innodb缓冲区现在可以估算主内存缓存区中的有多少表和索引,这可以让优化器选择访问方式时知道数据是否可以存储在内存中还是必须存储到磁盘上。
直方图histograms
通过使用直方图,用户或dba可以对数据分布进行统计,这可以用于查询优化以寻找优化的查询方案。
改进扫描性能
改进了innodb范围查询的性能,可提升全表查询和范围查询 5-20%的性能。
重构blob
重构blob加速了片段读取/更新操作,可以加速json数据的操作。
持久化自增值
innodb会持久化保持自增序列的最大值到redo日志中。这个改进还修复了一个非常老的199号bug。
临时表
取消对压缩临时表的支持,并存储临时表的元数据到内存中。
其它的更多重要改进和细节,请参考mysql 8.0.0 发布公告[1]和这里[2]。
下载
目前8.0.0还是开发版本,如果你希望体验和测试最新特性,可以从 dev.mysql.com[3] 下载各个平台的安装包。不过,mysql软件包是越来越大了,linux平台上的二进制打包后就将近有1 gb。如果在产品环境中使用,在8.0没有进入稳定版本之前,请继续使用5.7系列,当前最新的版本是5.7.15 ga版本——这只有600 m多。
最新的源代码放在 github 上,感兴趣的朋友可以去看看,其中有不少是中国人的贡献。
从mysql8.0开始支持隐藏索引特性,也就是所谓的invisible index。对于不可见的索引,优化器将直接忽略掉。我们可以通过该特性来影响优化器的行为。另外这也可以视为在drop一个索引之前的缓冲,临时把索引设置为不可见后,再观察应用是否正常或有报错什么的,如果一切ok,再最终删除。
对应的8.0.0的release note:
测试
# 创建一个普通的表t1,只带主键
mysql> create table t1 (a int primary key auto_increment, b int, c int, d int);
query ok, 0 rows affected (0.67 sec)
# 增加一个索引
mysql> alter table t1 add key(b);
query ok, 0 rows affected (0.06 sec)
records: 0 duplicates: 0 warnings: 0
mysql> show indexes from t1\g
*************************** 1. row ***************************
table: t1
non_unique: 0
key_name: primary
seq_in_index: 1
column_name: a
collation: a
cardinality: 0
sub_part: null
packed: null
null:
index_type: btree
comment:
index_comment:
visible: yes
*************************** 2. row ***************************
table: t1
non_unique: 1
key_name: b
seq_in_index: 1
column_name: b
collation: a
cardinality: 0
sub_part: null
packed: null
null: yes
index_type: btree
comment:
index_comment:
visible: yes
2 rows in set (0.01 sec)
从show indexes的visible列显示了,这两个索引都是可见的。
# load some data
insert into t1 select null, rand()*100000, rand()*10000,rand()*10000;
insert into t1 select null, rand()*100000, rand()*10000,rand()*10000 from t1;
insert into t1 select null, rand()*100000, rand()*10000,rand()*10000 from t1;
....
analyze table t1;
mysql> explain select * from t1 where b > 5000 limit 10;
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | extra |
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+
| 1 | simple | t1 | null | range | b | b | 5 | null | 1932 | 100.00| using index condition |
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec
可以看到索引b被使用到
# 修改索引b为不可见
mysql> alter table t1 alter index b invisible;
query ok, 0 rows affected (0.05 sec)
records: 0 duplicates: 0 warnings: 0
mysql> show indexes from t1\g
*************************** 1. row ***************************
table: t1
non_unique: 0
key_name: primary
seq_in_index: 1
column_name: a
collation: a
cardinality: 2048
sub_part: null
packed: null
null:
index_type: btree
comment:
index_comment:
visible: yes
*************************** 2. row ***************************
table: t1
non_unique: 1
key_name: b
seq_in_index: 1
column_name: b
collation: a
cardinality: 2029
sub_part: null
packed: null
null: yes
index_type: btree
comment:
index_comment:
visible: no
2 rows in set (0.01 sec)
mysql> explain select * from t1 where b > 5000 limit 10\g
*************************** 1. row ***************************
id: 1
select_type: simple
table: t1
partitions: null
type: all
possible_keys: null
key: null
key_len: null
ref: null
rows: 2048
filtered: 33.33
extra: using where
1 row in set, 1 warning (0.00 sec)
当索引被修改为invisible后,优化器将不再选择这个索引
# 将索引重新修改为可见
mysql> alter table t1 alter index b visible;
query ok, 0 rows affected (0.05 sec)
records: 0 duplicates: 0 warnings: 0
mysql> explain select * from t1 where b > 5000 limit 10\g
*************************** 1. row ***************************
id: 1
select_type: simple
table: t1
partitions: null
type: range
possible_keys: b
key: b
key_len: 5
ref: null
rows: 1932
filtered: 100.00
extra: using index condition
1 row in set, 1 warning (0.00 sec)
# 你也可以在创建索引的时候显式指定是否可见
mysql> alter table t1 add key(c) invisible;
query ok, 0 rows affected (0.12 sec)
records: 0 duplicates: 0 warnings: 0
mysql> show indexes from t1 where key_name = 'c'\g
*************************** 1. row ***************************
table: t1
non_unique: 1
key_name: c
seq_in_index: 1
column_name: c
collation: a
cardinality: 1848
sub_part: null
packed: null
null: yes
index_type: btree
comment:
index_comment:
visible: no
1 row in set (0.01 sec)
# 或者在建表时指定关键字
mysql> create table t2 (a int primary key, b int, key(b) invisible);
query ok, 0 rows affected (0.67 sec)
# 但primary key不可以设置为不可见
mysql> drop table t2;
query ok, 0 rows affected (0.03 sec)
mysql> create table t2 (a int, b int, primary key(a) invisible);
error 3522 (hy000): a primary key index cannot be invisible