对于新特性解读|MySQL8.0索引特性4-不可见索引感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍oracle不可见索引,并为您提供关于MySQL5.5新特性解读、MySQL8.0新特性--
对于新特性解读 | MySQL 8.0 索引特性 4 - 不可见索引感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍oracle不可见索引,并为您提供关于MySQL 5.5 新特性解读、MySQL 8.0新特性 -- 不可见索引、新特性解读 | InnoDB ReplicaSet:MySQL 副本集初体验、新特性解读 | MySQL 5.7 升级到 MySQL 8.0 的注意事项的有用信息。
本文目录一览:- 新特性解读 | MySQL 8.0 索引特性 4 - 不可见索引(oracle不可见索引)
- MySQL 5.5 新特性解读
- MySQL 8.0新特性 -- 不可见索引
- 新特性解读 | InnoDB ReplicaSet:MySQL 副本集初体验
- 新特性解读 | MySQL 5.7 升级到 MySQL 8.0 的注意事项
新特性解读 | MySQL 8.0 索引特性 4 - 不可见索引(oracle不可见索引)
MySQL 8.0 实现了索引的隐藏属性。当然这个特性很多商业数据库早就有了,比如 ORACLE,在 11g 中就实现了。我来介绍下这个小特性。
介绍
INVISIBLE INDEX,不可见索引或者叫隐藏索引。就是对优化器不可见,查询的时候优化器不会把她作为备选。
其实以前要想彻底不可见,只能用开销较大的 drop index;现在有了新的方式,可以改变索引的属性,让其不可见,这一操作只更改 metadata,开销非常小。
使用场景
我大概描述下有可能使用隐藏索引的场景:
1. 比如,我有张表 t1,本来已经有索引 idxf1,idxf2,idxf3。我通过数据字典检索到 idxf3 基本没有使用过,那我是不是可以判断这个索引直接删掉就好了?那如果删掉后突然有新上的业务要大量使用呢?难道我要频繁的 drop index/add index 吗?这个时候选择开销比较小的隐藏索引就好了。
2. 我的业务只有一个可能每个月固定执行一次的 SQL 用到这个索引,那选择隐藏索引太合适不过了。
3. 又或者是我想要测试下新建索引对我整个业务的影响程度。如果我直接建新索引,那我既有业务涉及到这个字段的有可能会收到很大影响。那这个时候隐藏索引也是非常合适的。
举例
下面我来简单举例如何使用隐藏索引:
表结构
mysql> create table f1 (id serial primary key, f1 int,f2 int );
Query OK, 0 rows affected (0.11 sec)
创建两个索引,默认可见。
索引 1,
mysql> alter table f1 add key idx_f1(f1), add key idx_f2(f2);
Query OK, 0 rows affected (0.12 sec)
Records: 0 Duplicates: 0 Warnings: 0
索引 2,
mysql> show create table f1\G
*************************** 1. row ***************************
Table: f1
Create Table: CREATE TABLE `f1` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`f1` int(11) DEFAULT NULL,
`f2` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`),
KEY `idx_f1` (`f1`),
KEY `idx_f2` (`f2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
简单写个造数据的存储过程。
DELIMITER $$
USE `ytt`$$
CREATE PROCEDURE `sp_generate_data_f1`(
IN f_cnt INT
)
BEGIN
DECLARE i,j INT DEFAULT 0;
SET @@autocommit=0;
WHILE i < f_cnt DO
SET i = i + 1;
IF j = 100 THEN
SET j = 0;
COMMIT;
END IF;
SET j = j + 1;
INSERT INTO f1 (f1,f2) SELECT CEIL(RAND()*100),CEIL(RAND()*100);
END WHILE;
COMMIT;
SET @@autocommit=1;
END$$
DELIMITER ;
生成 1W 条记录
mysql> call sp_generate_data_f1(10000);
Query OK, 0 rows affected (5.42 sec)
我们把 f2 列上的索引变为不可见,结果瞬间完成。
mysql> alter table f1 alter index idx_f2 invisible;
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0
在看下表结构,此时索引标记为 Invisible。
mysql> show create table f1 \G
*************************** 1. row ***************************
Table: f1
Create Table: CREATE TABLE `f1` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`f1` int(11) DEFAULT NULL,
`f2` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`),
KEY `idx_f1` (`f1`),
KEY `idx_f2` (`f2`) /*!80000 INVISIBLE */
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
给一条有 f2 列过滤的 SQL, 发现优化器用不到这个索引了。
mysql> explain select count(*) from f1 where f2 = 52\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: f1
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 9991
filtered: 1.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
用 force index 强制使用,直接报错。
mysql> explain select count(*) from f1 force index (idx_f2) where f2 = 52\G
ERROR 1176 (42000): Key ''idx_f2'' doesn''t exist in table ''f1''
那 MySQL 8.0 的优化器开关里可以告诉它,有的时候可以用隐藏索引。来打开看看。
mysql> set @@optimizer_switch = ''use_invisible_indexes=on'';
Query OK, 0 rows affected (0.00 sec)
那这条 SQL 现在可以用 idx_f2 了。
mysql> explain select count(*) from f1 where f2 = 52\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: f1
partitions: NULL
type: ref
possible_keys: idx_f2
key: idx_f2
key_len: 5
ref: const
rows: 121
filtered: 100.00
Extra: Using index
1 row in set, 1 warning (0.00 sec)
总结
INVISIBLE INDEX 的确是一个很有用的小特性,给索引增加了第三个额外的开关选项。想要了解更多的建议阅读 MySQL 手册。
社区近期动态
6 月 15 日 上海站
分布式中间件 DBLE 用户见面会
本次举办的 DBLE 用户见面会,是自 2017 年 10 月 24 日数据库中间件 DBLE 发布以来,首次线下互动式分享会议。
来爱可生总部研发中心,与研发、测试、产品、社区团队面对面,遇到志同道合的朋友,更有丰富精美的周边产品等着你!
会议时间:2019 年 06 月 15 日 13:00—17:00
会议地点:爱可生研发中心,上海市徐汇区虹梅路 1905 号远中科研楼甲幢 7 层
点击 “阅读原文”,进入报名详情页!!!
本文分享自微信公众号 - 爱可生开源社区(ActiontechOSS)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与 “OSC 源创计划”,欢迎正在阅读的你也加入,一起分享。
MySQL 5.5 新特性解读
新一代MySQL产品---MySQL5.5 已经面世,较之之前的5.1版本,将获得诸多特性方面的提升,简单总结如下:
1. 默认存储引擎更改为InnoDB
InnoDB作为成熟、高效的事务引擎,目前已经广泛使用,但MySQL5.1之前的版本默认引擎均为MyISAM,此次MySQL5.5终于 做到与时俱进,将默认数据库存储引擎改为InnoDB,并且引进了Innodb plugin 1.0.7。此次更新对数据库的好处是显而易见的:InnoDB的数据恢复时间从过去的一个甚至几个小时,缩短到几分钟(InnoDB plugin 1.0.7,InnoDB plugin 1.1, 恢复时采用红-黑树)。InnoDB Plugin 支持数据压缩存储,节约存储,提高内存命中率,并且支持adaptive flush checkpoint, 可以在某些场合避免数据库出现突发性能瓶颈。
Multi Rollback Segments: 原来InnoDB只有一个Segment,同时只支持1023的并发。现已扩充到128个Segments,从而解决了高并发的限制。
2. 多核性能提升
Metadata Locking (MDL) Framework替换LOCK_open mutex (lock),使得MySQL5.1及过去版本在多核心处理器上的性能瓶颈得到解决,官方表示将继续增强对MySQL多处理器支持,直至MySQL性能 “不受处理器数量的限制”
3. 复制功能(Replication)加强
MySQL复制特性是互联网公司应用非常广泛的特性,作为MySQL最实用最简单的扩展方式,过去的异步复制方式已经有些不上形势,对某些用户 来说“异步复制”意味着极端情况下的数据风险,MySQL5.5将首次支持半同步(semi-sync replication)在MySQL的高可用方案中将产生更多更加可靠的方案。另外Slave fsync tunning;Relay log corruption recovery和Replication Heartbeat也将实现
4. 增强表分区功能
MySQL 5.5的分区对用户绝对是个好消息,更易于使用的增强功能,以及TRUNCATE PARTITION命令都可以为DBA节省大量的时间,有时对最终用户亦如此:
1) 非整数列分区:任何使用过MySQL分区的人应该都遇到过不少问题,特别是面对非整数列分区时,MySQL 5.1只能处理整数列分区,如果你想在日期或字符串列上进行分区,你不得不使用函数对其进行转换。很麻烦,而MySQL 5.5中新增了两类分区方法,RANG和LIST分区法,同时在新的函数中增加了一个COLUMNS关键词。在MySQL 5.1中使用分区另一个让人头痛的问题是date类型(即日期列),你不能直接使用它们,必须使用YEAR或TO_DAYS转换这些列,但在MySQL 5.5中情况发生了很大的变化,现在在日期列上可以直接分区,并且方法也很简单;
2) 多列分区:COLUMNS关键字现在允许字符串和日期列作为分区定义列,同时还允许使用多个列定义一个分区;
3) 可用性增强:truncate分区。分区最吸引人的一个功能是瞬间移除大量记录的能力,DBA都喜欢将历史记录存储到按日期分区的分区表中,这样可以定期 删除过时的历史数据。 但当你需要移除分区中的部分数据时,事情就不是那么简单了,删除分区没有问题,但如果是清空分区,就很头痛了,要移除分区中的所有 数据,但需要保留分区本身,你可以:使用DELETE语句,但我们知道DELETE语句的性能都很差。使用DROP PARTITION语句,紧跟着一个EORGANIZE PARTITIONS语句重新创建分区,但这样做比前一个方法的成本要高出许多。MySQL 5.5引入了TRUNCATE PARTITION,它和DROP PARTITION语句有些类似,但它保留了分区本身,也就是说分区还可以重复利用。TRUNCATE PARTITION应该是DBA工具箱中的必备工具;
4) 更多微调功能:TO_SECONDS:分区增强包有一个新的函数处理DATE和DATETIME列,使用TO_SECONDS函数,你可以将日期/时间列转换成自0年以来的秒数,如果你想使用小于1天的间隔进行分区,那么这个函数就可以帮到你。
5. Insert Buffering 如果在buffer pool中没找到数据,那么直接buffer起来,避免额外的IO;Delete & Purge Buffering 跟插入一样,如果buffer pool中没有命中,先buffer起来,避免额外的IO。
6. Support for Native AIO on Linux
以上的特性在MySQL 5.5的社区版当中都将包括,在MySQL企业版当中,除以上更新之外,Oracle还加强了更多实用的企业级功能,包括:
1. 实现在线物理热备
MySQL 企业版将包含Innodb Hotbackup(这也许是MySQL和InnDB多年之后重新聚首的新亮点),从而一举解决过去MySQL无法进行可靠的在线实时物理备份的问题, InnoDB Hot Backup 不需要你关闭你的服务器也不需要加任何锁或影响其它普通的数据操作,这对MySQL DBA来说应该是一个不错的消息。
2. MySQL Enterprise Monitor 2.2 & Oracle Enterprise Monitor
是的,你没有看错,MySQL将可以被Oracle Enterprise Monitor监控,这是一个实现起来并不复杂,但在过去绝无可能的变化。并且MySQL企业版监控器(MySQL Enterprise Monitor)得到了更大的加强,版本更新至2.2,对MySQL服务器资源占用降低到可以忽略的地步,集成了监控,报警,SQL语句分析和给出优化建 议,MySQL的一些开源监控方案相比之下显得过于简陋,对企业客户来说,MySQL变得更加可靠。
3. MySQL Workbench
过去MySQL的图形界面工具做的实在是令人难以恭维,当然这也给众多MySQL管理工具提供了市场空间,现在Oracle打算将MySQL做 得比SQL-Server更加简单易用,MySQL Workbench是一款专为MySQL设计的ER/数据库建模工具,可以用来设计和创建新的数据库图示,建立数据库文档,以及进行复杂的MySQL 迁移等操作,因此内置workbench将使MySQL使用起来更简便高效。
4. 关于未来的重要提醒:Oracle的管理工具,MySQL也将能够使用,当然MySQL 5.5我们还没看到这个变化,但变化已经在时间表上,MySQL社区版也能够被Oracle管理工具管理,前提你得是Oracle数据库的用户。
MySQL 8.0新特性 -- 不可见索引
MySQL支持不可见索引,即优化器不会使用该索引。
不可见索引特性不可以用于主键。
默认索引是可见的。可以在create table、create index、alter table操作中使用关键字visible、invisible来指定索引是否可见。
create table t1 (
i int,
j int,
k int,
index i_idx (i) invisible
) engine = innodb;
create index j_idx on t1 (j) invisible;
alter table t1 add index k_idx (k) invisible;
修改已经存在的索引的可见性:
alter table t1 alter index i_idx invisible;
alter table t1 alter index i_idx visible;
可以通过information_schema.statistics、show index查看索引的可见性:
>select index_name, is_visible
-> from information_schema.statistics
-> where table_schema = ''abce'' and table_name = ''t1'';
+------------+------------+
| INDEX_NAME | IS_VISIBLE |
+------------+------------+
| i_idx | NO |
+------------+------------+
1 row in set (0.00 sec)
>show index from t1;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| t1 | 1 | i_idx | 1 | i | A | 0 | NULL | NULL | YES | BTREE | | | NO | NULL |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
1 row in set (0.00 sec)
不可见索引可以用来测试移除索引后对查询性能的影响。毕竟对于大表,删除和重建索引是非常昂贵的操作。
系统变量optimizer_switch中的use_invisible_indexes标志控制了优化器是否使用不可见索引来构建执行计划。
如果use_invisible_indexes=off(默认设置),优化器会忽略不可见索引;如果设置为on,索引仍然不可见,但是优化器在生成执行计划的时候会考虑不可见索引。
新特性解读 | InnoDB ReplicaSet:MySQL 副本集初体验
MySQL 副本集(官方名称:MySQL InnoDB ReplicaSet)在 MySQL 8.0.19 版本(2020-01-13 Released)之后开始支持,本质还是是基于 GTID 的异步复制
角色分为 Primary 和 Secondary
1)Primary 即传统意义上的 Master,一个副本集只允许一个 2)Secondary 即 Slave,允许一个或多个 -
通过 MySQL Shell 自带的 AdminAPI 创建、配置、删除等管理副本集 -
通过 MySQL Router 使用副本集,引导与连接方式与 InnoDB Cluster 和 MGR 有点类似,不同之处在于新增了 cluster_type = rs 集群类型。
二、通过 MySQL Shell 部署 Sandbox 实例
MySQL Shell 除了集成 AdminAPI 外还提供了 MySQL Sandbox 功能,可轻松部署用以测试的 MySQL 数据库实例
通过 Sandbox 一键部署三个 MySQL 实例
# mysqlsh
MySQL JS > dba.deploySandboxInstance(3306)
MySQL JS > dba.deploySandboxInstance(3307)
MySQL JS > dba.deploySandboxInstance(3308)
创建集群管理员账户 repl 作为具有管理 InnoDB ReplicaSet 所需的权限集合
MySQL JS > dba.configureReplicaSetInstance(''root@localhost:3306'', {clusterAdmin: "''repl''@''%''", clusterAdminPassword: ''repl''});
3.2 创建 InnoDB 副本集
连接到第一个 MySQL 实例 3306,创建命名为 renzy 的副本集
MySQL JS > \connect root@localhost:3306
MySQL localhost:3306 ssl JS > var rs = dba.createReplicaSet("renzy")
-
查看副本集状态,默认第一个实例 3306 选举为 Primary 节点
MySQL localhost:3306 ssl JS > rs.status()
{
"replicaSet": {
"name": "renzy",
"primary": "127.0.0.1:3306",
"status": "AVAILABLE",
"statusText": "All instances available.",
"topology": {
"127.0.0.1:3306": {
"address": "127.0.0.1:3306",
"instanceRole": "PRIMARY",
"mode": "R/W",
"status": "ONLINE"
}
},
"type": "ASYNC"
}
}
3.3 添加节点到副本集
MySQL localhost:3306 ssl JS > rs.addInstance(''localhost:3307'')
MySQL localhost:3306 ssl JS > rs.addInstance(''localhost:3308'')
添加节点 3307 和 3308 到副本集涉及到数据拷贝有两种方式:Clone 全量同步和 Inremental recovery 增量同步,本文使用 Clone 全量同步方式从 Primary 节点全量同步数据
查看副本集状态,已添加到副本集的实例 3307 和 3308 的角色为 Secondary ,并自动与 Primary 节点 3306 建立复制关系
MySQL localhost:3306 ssl JS > rs.status()
{
"replicaSet": {
"name": "renzy",
"primary": "127.0.0.1:3306",
"status": "AVAILABLE",
"statusText": "All instances available.",
"topology": {
"127.0.0.1:3306": {
"address": "127.0.0.1:3306",
"instanceRole": "PRIMARY",
"mode": "R/W",
"status": "ONLINE"
},
"127.0.0.1:3307": {
"address": "127.0.0.1:3307",
"instanceRole": "SECONDARY",
"mode": "R/O",
"replication": {
"applierStatus": "APPLIED_ALL",
"applierThreadState": "Slave has read all relay log; waiting for more updates",
"receiverStatus": "ON",
"receiverThreadState": "Waiting for master to send event",
"replicationLag": null
},
"status": "ONLINE"
},
"127.0.0.1:3308": {
"address": "127.0.0.1:3308",
"instanceRole": "SECONDARY",
"mode": "R/O",
"replication": {
"applierStatus": "APPLIED_ALL",
"applierThreadState": "Slave has read all relay log; waiting for more updates",
"receiverStatus": "ON",
"receiverThreadState": "Waiting for master to send event",
"replicationLag": null
},
"status": "ONLINE"
}
},
"type": "ASYNC"
}
}
手工在线将实例 3308 切换为 Primary 节点
MySQL localhost:3306 ssl JS > rs.setPrimaryInstance(''127.0.0.1:3308'')
实例 3308 被提升为 Primary 后,副本集将自动将 实例 3306 降级为 Secondary 并与 3308 建立复制关系,副本集中其它实例 3307 也将自动与 3308 建立复制与同步
MySQL localhost:3306 ssl JS > rs.status()
{
"replicaSet": {
"name": "renzy",
"primary": "127.0.0.1:3308",
"status": "AVAILABLE",
"statusText": "All instances available.",
"topology": {
"127.0.0.1:3306": {
"address": "127.0.0.1:3306",
"instanceRole": "SECONDARY",
"mode": "R/O",
"replication": {
"applierStatus": "APPLIED_ALL",
"applierThreadState": "Slave has read all relay log; waiting for more updates",
"receiverStatus": "ON",
"receiverThreadState": "Waiting for master to send event",
"replicationLag": null
},
"status": "ONLINE"
},
"127.0.0.1:3307": {
"address": "127.0.0.1:3307",
"instanceRole": "SECONDARY",
"mode": "R/O",
"replication": {
"applierStatus": "APPLIED_ALL",
"applierThreadState": "Slave has read all relay log; waiting for more updates",
"receiverStatus": "ON",
"receiverThreadState": "Waiting for master to send event",
"replicationLag": null
},
"status": "ONLINE"
},
"127.0.0.1:3308": {
"address": "127.0.0.1:3308",
"instanceRole": "PRIMARY",
"mode": "R/W",
"status": "ONLINE"
}
},
"type": "ASYNC"
}
}
手工杀掉 Primary 节点进程
# ps -ef | grep 3308
root 18975 1 0 16:52 ? 00:01:23 /root/mysql-sandboxes/3308/bin/mysqld --defaults-file=/root/mysql-sandboxes/3308/my.cnf --user=root
# kill -9 18975
副本集 无法自动进行故障转移 ,需要人工介入修复
-
手工将 Secondary 节点 3306 强制提升为 Primary
MySQL localhost:3306 ssl JS > rs.forcePrimaryInstance("127.0.0.1:3306")
副本集恢复后,因 3308 不可用副本集状态显示为 AVAIABLE_PARITAL (部分可用)
四、通过 MySQL Router 使用副本集
与使用 MySQL Router 连接 MGR 或 InnoDB Cluster 一样,副本集也可以通过 MySQL Router 访问,首先通过 --bootstrap 选项引导副本集
mysqlrouter --user=root --bootstrap root@localhost:3308
五、MySQL Router 通过 R/W 自动连接到 Primary
启动 MySQL Router
mysqlrouter -c /usr/local/mysql-router-8.0.19-linux-glibc2.12-x86_64/mysqlrouter.conf &
// 通过 MySQL Router R/W 端口可以自动识别并连接到 Primary
# mysql -h10.186.63.158 -P6446 -uroot -proot -e ''select @@port;''
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------+
| @@port |
+--------+
| 3308 |
+--------+
# mysql -h10.186.63.158 -P6446 -uroot -proot -e ''show slave hosts;''
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+-----------+------+------------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+------------+-----------+------+------------+--------------------------------------+
| 1587786506 | 127.0.0.1 | 3307 | 2457151498 | cb569215-3b29-11ea-80f4-02000aba3f9e |
| 3616586416 | 127.0.0.1 | 3306 | 2457151498 | c23ee4be-3b29-11ea-815a-02000aba3f9e |
+------------+-----------+------+------------+--------------------------------------+
-
副本集主从切换后,MySQL Router R/W 自动指向被选举出来的新的 Primary
六、结论
1. MySQL Router 可以很好的兼容 InnoDB ReplicaSet,可自动识别到副本集主从切换,将新的 R/W 连接指向 Primary。
2. InnoDB ReplicaSet 当前还不完善,可作为新特性在测试环境试用,但因为不支持自动故障转移,Primary 宕机整个副本集将不可用。
3. InnoDB ReplicaSet 目前仅支持基于 GTID 的异步复制,哪怕支持自动切换,数据也有丢失风险,所以离真正部署到生产环境还有一段路要走。
4. InnoDB ReplicaSet 暂时还没有类似芒果 DB 完善的投票选举机制,故障切换时也会存在脑裂风险。
总之,InnoDB 副本集虽存在诸多不足之处,但作为 2020 年 Oracle 的开餐甜点其带来的效果也让众多 MySQL DBA 眼前一亮,既然有了副本集,相信 Sharding 也是未来可期,你觉得呢?

社区近期动态

点一下“阅读原文”了解更多资讯
