Maison > Article > base de données > Résumé des nouvelles fonctionnalités de MySQL8.0 (avec code)
Le contenu de cet article est un résumé des nouvelles fonctionnalités de MySQL8.0 (avec code). Il a une certaine valeur de référence. J'espère qu'il sera utile. pour vous.
1. Le jeu de caractères par défaut passe de latin1 à utf8mb4
Avant la version 8.0, le jeu de caractères par défaut était latin1, utf8 pointait vers utf8mb3 et le jeu de caractères par défaut dans la version 8.0, il s'agit de utf8mb4, et utf8 pointe également vers utf8mb4 par défaut.
(Recommandé : Tutoriel MySQL)
2. Remplacez toutes les tables système MyISAM par des tables InnoDB
Remplacez toutes les tables système En tant que table innodb transactionnelle, l'instance MySQL par défaut ne contiendra aucune table MyISAM, sauf si vous créez manuellement une table MyISAM.
# MySQL 5.7 mysql> select distinct(ENGINE) from information_schema.tables; +--------------------+ | ENGINE | +--------------------+ | MEMORY | | InnoDB | | MyISAM | | CSV | | PERFORMANCE_SCHEMA | | NULL | +--------------------+ 6 rows in set (0.00 sec) # MySQL 8.0 mysql> select distinct(ENGINE) from information_schema.tables; +--------------------+ | ENGINE | +--------------------+ | NULL | | InnoDB | | CSV | | PERFORMANCE_SCHEMA | +--------------------+ 4 rows in set (0.00 sec)
Dans les versions antérieures à 8.0, si la valeur de la clé primaire auto-incrémentée AUTO_INCREMENT est supérieure à max (clé primaire) + 1, après MySQL est redémarré, il réinitialisera AUTO_INCREMENT=max(primary key)+1. Ce phénomène peut entraîner des conflits de clés primaires métier ou d'autres problèmes difficiles à trouver dans certains cas. Le problème du redémarrage et de la réinitialisation de la clé primaire auto-incrémentée a été découvert très tôt (https://bugs.mysql.com/bug.ph...) et n'a été résolu que lorsque la version 8.0 conservera la valeur AUTO_INCREMENT. ne changera pas après le redémarrage de MySQL.
Le DDL de la table InnoDB prend en charge l'intégrité des transactions, qu'elles soient réussies ou annulées, et le journal d'annulation des opérations DDL est écrit dans la table du dictionnaire de données du dictionnaire de données mysql.innodb_ddl_log. . Utilisé pour les opérations de restauration. Cette table est masquée et ne peut pas être vue via les tables d'affichage. En définissant les paramètres, le journal des opérations ddl peut être imprimé dans le journal des erreurs mysql.
mysql> set global log_error_verbosity=3; mysql> set global innodb_print_ddl_logs=1; mysql> create table t1(c int) engine=innodb; # MySQL错误日志: 2018-06-26T11:25:25.817245+08:00 44 [Note] [MY-012473] [InnoDB] InnoDB: DDL log insert : [DDL record: DELETE SPACE, id=41, thread_id=44, space_id=6, old_file_path=./db/t1.ibd] 2018-06-26T11:25:25.817369+08:00 44 [Note] [MY-012478] [InnoDB] InnoDB: DDL log delete : by id 41 2018-06-26T11:25:25.819753+08:00 44 [Note] [MY-012477] [InnoDB] InnoDB: DDL log insert : [DDL record: REMOVE CACHE, id=42, thread_id=44, table_id=1063, new_file_path=db/t1] 2018-06-26T11:25:25.819796+08:00 44 [Note] [MY-012478] [InnoDB] InnoDB: DDL log delete : by id 42 2018-06-26T11:25:25.820556+08:00 44 [Note] [MY-012472] [InnoDB] InnoDB: DDL log insert : [DDL record: FREE, id=43, thread_id=44, space_id=6, index_id=140, page_no=4] 2018-06-26T11:25:25.820594+08:00 44 [Note] [MY-012478] [InnoDB] InnoDB: DDL log delete : by id 43 2018-06-26T11:25:25.825743+08:00 44 [Note] [MY-012485] [InnoDB] InnoDB: DDL log post ddl : begin for thread id : 44 2018-06-26T11:25:25.825784+08:00 44 [Note] [MY-012486] [InnoDB] InnoDB: DDL log post ddl : end for thread id : 44
Regardons un autre exemple. Il n'y a qu'une seule table t1 dans la bibliothèque, supprimez la table t1, t2 en essayant de supprimer deux tables t1 et t2, en 5.7, une erreur est signalée lors de l'exécution, mais la table t1 est supprimée. Une erreur est signalée lors de l'exécution dans la version 8.0, mais la table t1 n'est pas supprimée, ce qui prouve l'atomicité des opérations DDL 8.0. Soit toutes les opérations réussissent, soit elles sont annulées.
# MySQL 5.7 mysql> show tables; +---------------+ | Tables_in_db | +---------------+ | t1 | +---------------+ 1 row in set (0.00 sec) mysql> drop table t1, t2; ERROR 1051 (42S02): Unknown table 'db.t2' mysql> show tables; Empty set (0.00 sec) # MySQL 8.0 mysql> show tables; +---------------+ | Tables_in_db | +---------------+ | t1 | +---------------+ 1 row in set (0.00 sec) mysql> drop table t1, t2; ERROR 1051 (42S02): Unknown table 'db.t2' mysql> show tables; +---------------+ | Tables_in_db | +---------------+ | t1 | +---------------+ 1 row in set (0.00 sec)
MySQL version 8.0 prend en charge la modification en ligne des paramètres globaux et la persistance En ajoutant le mot-clé PERSIST, les paramètres modifiés peuvent être conservés dans la configuration. (mysqld-auto.cnf), lors du redémarrage de MySQL, vous pouvez obtenir les derniers paramètres de configuration à partir de ce fichier de configuration.
Par exemple, exécutez :
set PERSIST expire_logs_days=10 ;
Le système générera un fichier contenant mysqld-auto.cnf au format json dans le répertoire de données. Après formatage, c'est comme suit. .cnf et Lorsque mysqld-auto.cnf existe en même temps, ce dernier a une priorité plus élevée.
{ "Version": 1, "mysql_server": { "expire_logs_days": { "Value": "10", "Metadata": { "Timestamp": 1529657078851627, "User": "root", "Host": "localhost" } } } }
MySQL prend en charge les index descendants dans la syntaxe depuis longtemps, mais en fait, l'index ascendant est toujours créé, comme indiqué dans MySQL 5.7 ci-dessous, c2 Les champs sont par ordre décroissant, mais d'après show create table, c2 est toujours par ordre croissant. 8.0 peut voir que le champ c2 est par ordre décroissant.
# MySQL 5.7 mysql> create table t1(c1 int,c2 int,index idx_c1_c2(c1,c2 desc)); Query OK, 0 rows affected (0.03 sec) mysql> show create table t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `c1` int(11) DEFAULT NULL, `c2` int(11) DEFAULT NULL, KEY `idx_c1_c2` (`c1`,`c2`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 1 row in set (0.00 sec) # MySQL 8.0 mysql> create table t1(c1 int,c2 int,index idx_c1_c2(c1,c2 desc)); Query OK, 0 rows affected (0.06 sec) mysql> show create table t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `c1` int(11) DEFAULT NULL, `c2` int(11) DEFAULT NULL, KEY `idx_c1_c2` (`c1`,`c2` DESC) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC 1 row in set (0.00 sec)
Jetons un coup d'œil aux performances de l'index descendant dans le plan d'exécution. Insérez 100 000 éléments de données aléatoires dans la table t1 et vérifions le plan d'exécution de select * from t1 order by c1, c2. desc;. Il ressort du plan d'exécution que le numéro d'analyse de 100113 dans la version 5.7 est beaucoup plus grand que les 5 lignes de la version 8.0 et que le tri de fichiers est utilisé.
DELIMITER ;; CREATE PROCEDURE test_insert () BEGIN DECLARE i INT DEFAULT 1; WHILE i<100000 DO insert into t1 select rand()*100000, rand()*100000; SET i=i+1; END WHILE ; commit; END;; DELIMITER ; CALL test_insert(); # MySQL 5.7 mysql> explain select * from t1 order by c1 , c2 desc limit 5; +----+-------------+-------+------------+-------+---------------+-----------+---------+------+--------+----------+-----------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+-----------+---------+------+--------+----------+-----------------------------+ | 1 | SIMPLE | t1 | NULL | index | NULL | idx_c1_c2 | 10 | NULL | 100113 | 100.00 | Using index; Using filesort | +----+-------------+-------+------------+-------+---------------+-----------+---------+------+--------+----------+-----------------------------+ 1 row in set, 1 warning (0.00 sec) # MySQL 8.0 mysql> explain select * from t1 order by c1 , c2 desc limit 5; +----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+ | 1 | SIMPLE | t1 | NULL | index | NULL | idx_c1_c2 | 10 | NULL | 5 | 100.00 | Using index | +----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)
L'index décroissant n'est efficace que pour l'ordre de tri spécifique dans la requête. S'il est utilisé de manière incorrecte, l'efficacité de la requête sera inférieure. Par exemple, la condition de tri de la requête ci-dessus est modifiée en ordre par c1 desc, c2 desc. Dans ce cas, le plan d'exécution de 5.7 est nettement meilleur que celui de 8.0, comme suit :
# MySQL 5.7 mysql> explain select * from t1 order by c1 desc , c2 desc limit 5; +----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+ | 1 | SIMPLE | t1 | NULL | index | NULL | idx_c1_c2 | 10 | NULL | 5 | 100.00 | Using index | +----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.01 sec) # MySQL 8.0 mysql> explain select * from t1 order by c1 desc , c2 desc limit 5; +----+-------------+-------+------------+-------+---------------+-----------+---------+------+--------+----------+-----------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+-----------+---------+------+--------+----------+-----------------------------+ | 1 | SIMPLE | t1 | NULL | index | NULL | idx_c1_c2 | 10 | NULL | 100429 | 100.00 | Using index; Using filesort | +----+-------------+-------+------------+-------+---------------+-----------+---------+------+--------+----------+-----------------------------+ 1 row in set, 1 warning (0.01 sec)
mysql 8.0. trie implicitement le champ group by. Si un tri est requis, la clause order by doit être explicitement ajoutée.
# 表结构 mysql> show create table tb1\G *************************** 1. row *************************** Table: tb1 Create Table: CREATE TABLE `tb1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, `group_own` int(11) DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC 1 row in set (0.00 sec) # 表数据 mysql> select * from tb1; +----+------+-----------+ | id | name | group_own | +----+------+-----------+ | 1 | 1 | 0 | | 2 | 2 | 0 | | 3 | 3 | 0 | | 4 | 4 | 0 | | 5 | 5 | 5 | | 8 | 8 | 1 | | 10 | 10 | 5 | +----+------+-----------+ 7 rows in set (0.00 sec) # MySQL 5.7 mysql> select count(id), group_own from tb1 group by group_own; +-----------+-----------+ | count(id) | group_own | +-----------+-----------+ | 4 | 0 | | 1 | 1 | | 2 | 5 | +-----------+-----------+ 3 rows in set (0.00 sec) # MySQL 8.0.11 mysql> select count(id), group_own from tb1 group by group_own; +-----------+-----------+ | count(id) | group_own | +-----------+-----------+ | 4 | 0 | | 2 | 5 | | 1 | 1 | +-----------+-----------+ 3 rows in set (0.00 sec) # MySQL 8.0.11显式地加上order by进行排序 mysql> select count(id), group_own from tb1 group by group_own order by group_own; +-----------+-----------+ | count(id) | group_own | +-----------+-----------+ | 4 | 0 | | 1 | 1 | | 2 | 5 | +-----------+-----------+ 3 rows in set (0.00 sec)
MySQL 8 a considérablement amélioré sa prise en charge de JSON, en ajoutant la fonction JSON_EXTRACT() pour extraire les données des champs JSON en fonction des paramètres de requête de chemin et en utilisant Les fonctions d'agrégation JSON_ARRAYAGG() et JSON_OBJECTAGG() permettent respectivement de combiner des données dans des tableaux et des objets JSON.
Dans la réplication maître-esclave, le nouveau paramètre binlog_row_value_options est ajouté pour contrôler la méthode de transmission des données JSON. Il permet une modification partielle du type Json. Seule la partie modifiée est enregistrée dans le binlog, réduisant ainsi la situation. où il n'y a que quelques modifications au json big data Down, l'occupation des ressources.
Ajoutez les deux paramètres suivants pour contrôler le cryptage des journaux de rétablissement et d'annulation.
innodb_undo_log_encrypt
innodb_undo_log_encrypt
sélectionnez ... pour la mise à jour, sélectionnez ... pour le partage (nouvelle syntaxe 8.0) Ajoutez NOWAIT, Syntaxe SKIP LOCKED, ignorer l'attente du verrouillage ou ignorer le verrouillage.
Dans les versions 5.7 et antérieures, sélectionnez... pour la mise à jour, si le verrou ne peut pas être obtenu, attendra que innodb_lock_wait_timeout expire.
Dans la version 8.0, en ajoutant la syntaxe nowait et skip verrouillé, vous pouvez revenir immédiatement. Si la ligne interrogée a été verrouillée, nowait renverra immédiatement une erreur et skip verrouillé renverra également immédiatement, mais le résultat renvoyé n'inclura pas la ligne verrouillée.
# session1: mysql> begin; mysql> select * from t1 where c1 = 2 for update; +------+-------+ | c1 | c2 | +------+-------+ | 2 | 60530 | | 2 | 24678 | +------+-------+ 2 rows in set (0.00 sec) # session2: mysql> select * from t1 where c1 = 2 for update nowait; ERROR 3572 (HY000): Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set. mysql> select * from t1 where c1 = 2 for update skip locked; Empty set (0.00 sec)
Ajoutez la syntaxe SET_VAR dans la syntaxe SQL pour ajuster dynamiquement certains paramètres, ce qui contribuera à améliorer les performances des instructions.
使用INVISIBLE关键字在创建表或者进行表变更中设置索引是否可见。索引不可见只是在查询时优化器不使用该索引,即使使用force index,优化器也不会使用该索引,同时优化器也不会报索引不存在的错误,因为索引仍然真实存在,在必要时,也可以快速的恢复成可见。
# 创建不可见索引 create table t2(c1 int,c2 int,index idx_c1_c2(c1,c2 desc) invisible ); # 索引可见 alter table t2 alter index idx_c1_c2 visible; # 索引不可见 alter table t2 alter index idx_c1_c2 invisible;
优化器会利用column_statistics的数据,判断字段的值的分布,得到更准确的执行计划。
可以使用 ANALYZE TABLE table_name [UPDATE HISTOGRAM on col_name with N BUCKETS |DROP HISTOGRAM ON clo_name] 来收集或者删除直方图信息。
直方图统计了表中某些字段的数据分布情况,为优化选择高效的执行计划提供参考,直方图与索引有着本质的区别,维护一个索引有代价。每一次的insert、update、delete都会需要更新索引,会对性能有一定的影响。而直方图一次创建永不更新,除非明确去更新它。所以不会影响insert、update、delete的性能。
# 添加/更新直方图 mysql> analyze table t1 update histogram on c1, c2 with 32 buckets; +--------+-----------+----------+-----------------------------------------------+ | Table | Op | Msg_type | Msg_text | +--------+-----------+----------+-----------------------------------------------+ | db.t1 | histogram | status | Histogram statistics created for column 'c1'. | | db.t1 | histogram | status | Histogram statistics created for column 'c2'. | +--------+-----------+----------+-----------------------------------------------+ 2 rows in set (2.57 sec) # 删除直方图 mysql> analyze table t1 drop histogram on c1, c2; +--------+-----------+----------+-----------------------------------------------+ | Table | Op | Msg_type | Msg_text | +--------+-----------+----------+-----------------------------------------------+ | db.t1 | histogram | status | Histogram statistics removed for column 'c1'. | | db.t1 | histogram | status | Histogram statistics removed for column 'c2'. | +--------+-----------+----------+-----------------------------------------------+ 2 rows in set (0.13 sec)
能够让InnoDB根据服务器上检测到的内存大小自动配置innodb_buffer_pool_size,innodb_log_file_size,innodb_flush_method三个参数。
在错误信息中添加了错误信息编号[MY-010311]和错误所属子系统[Server]
# MySQL 5.7 2018-06-08T09:07:20.114585+08:00 0 [Warning] 'proxies_priv' entry '@ root@localhost' ignored in --skip-name-resolve mode. 2018-06-08T09:07:20.117848+08:00 0 [Warning] 'tables_priv' entry 'user mysql.session@localhost' ignored in --skip-name-resolve mode. 2018-06-08T09:07:20.117868+08:00 0 [Warning] 'tables_priv' entry 'sys_config mysql.sys@localhost' ignored in --skip-name-resolve mode. # MySQL 8.0 2018-06-21T17:53:13.040295+08:00 28 [Warning] [MY-010311] [Server] 'proxies_priv' entry '@ root@localhost' ignored in --skip-name-resolve mode. 2018-06-21T17:53:13.040520+08:00 28 [Warning] [MY-010330] [Server] 'tables_priv' entry 'user mysql.session@localhost' ignored in --skip-name-resolve mode. 2018-06-21T17:53:13.040542+08:00 28 [Warning] [MY-010330] [Server] 'tables_priv' entry 'sys_config mysql.sys@localhost' ignored in --skip-name-resolve mode.
MySQL 8.0新增了一个资源组功能,用于调控线程优先级以及绑定CPU核。
MySQL用户需要有 RESOURCE_GROUP_ADMIN权限才能创建、修改、删除资源组。
在Linux环境下,MySQL进程需要有 CAP_SYS_NICE 权限才能使用资源组完整功能。
[root@localhost~]# sudo setcap cap_sys_nice+ep /usr/local/mysql8.0/bin/mysqld [root@localhost~]# getcap /usr/local/mysql8.0/bin/mysqld /usr/local/mysql8.0/bin/mysqld = cap_sys_nice+ep
默认提供两个资源组,分别是USR_default,SYS_default
创建资源组:
create resource group test_resouce_group type=USER vcpu=0,1 thread_priority=5;
将当前线程加入资源组:
SET RESOURCE GROUP test_resouce_group;
将某个线程加入资源组:
SET RESOURCE GROUP test_resouce_group FOR thread_id;
查看资源组里有哪些线程:
select * from Performance_Schema.threads where RESOURCE_GROUP='test_resouce_group';
修改资源组:
alter resource group test_resouce_group vcpu = 2,3 THREAD_PRIORITY = 8;
删除资源组 :
drop resource group test_resouce_group;
# 创建资源组 mysql>create resource group test_resouce_group type=USER vcpu=0,1 thread_priority=5; Query OK, 0 rows affected (0.03 sec) mysql> select * from RESOURCE_GROUPS; +---------------------+---------------------+------------------------+----------+-----------------+ | RESOURCE_GROUP_NAME | RESOURCE_GROUP_TYPE | RESOURCE_GROUP_ENABLED | VCPU_IDS | THREAD_PRIORITY | +---------------------+---------------------+------------------------+----------+-----------------+ | USR_default | USER | 1 | 0-3 | 0 | | SYS_default | SYSTEM | 1 | 0-3 | 0 | | test_resouce_group | USER | 1 | 0-1 | 5 | +---------------------+---------------------+------------------------+----------+-----------------+ 3 rows in set (0.00 sec) # 把线程id为60的线程加入到资源组test_resouce_group中,线程id可通过Performance_Schema.threads获取 mysql> SET RESOURCE GROUP test_resouce_group FOR 60; Query OK, 0 rows affected (0.00 sec) # 资源组里有线程时,删除资源组报错 mysql> drop resource group test_resouce_group; ERROR 3656 (HY000): Resource group test_resouce_group is busy. # 修改资源组 mysql> alter resource group test_resouce_group vcpu = 2,3 THREAD_PRIORITY = 8; Query OK, 0 rows affected (0.10 sec) mysql> select * from RESOURCE_GROUPS; +---------------------+---------------------+------------------------+----------+-----------------+ | RESOURCE_GROUP_NAME | RESOURCE_GROUP_TYPE | RESOURCE_GROUP_ENABLED | VCPU_IDS | THREAD_PRIORITY | +---------------------+---------------------+------------------------+----------+-----------------+ | USR_default | USER | 1 | 0-3 | 0 | | SYS_default | SYSTEM | 1 | 0-3 | 0 | | test_resouce_group | USER | 1 | 2-3 | 8 | +---------------------+---------------------+------------------------+----------+-----------------+ 3 rows in set (0.00 sec) # 把资源组里的线程移出到默认资源组USR_default mysql> SET RESOURCE GROUP USR_default FOR 60; Query OK, 0 rows affected (0.00 sec) # 删除资源组 mysql> drop resource group test_resouce_group; Query OK, 0 rows affected (0.04 sec)
角色可以认为是一些权限的集合,为用户赋予统一的角色,权限的修改直接通过角色来进行,无需为每个用户单独授权。
# 创建角色 mysql> create role role_test; Query OK, 0 rows affected (0.03 sec) # 给角色授予权限 mysql> grant select on db.* to 'role_test'; Query OK, 0 rows affected (0.10 sec) # 创建用户 mysql> create user 'read_user'@'%' identified by '123456'; Query OK, 0 rows affected (0.09 sec) # 给用户赋予角色 mysql> grant 'role_test' to 'read_user'@'%'; Query OK, 0 rows affected (0.02 sec) # 给角色role_test增加insert权限 mysql> grant insert on db.* to 'role_test'; Query OK, 0 rows affected (0.08 sec) # 给角色role_test删除insert权限 mysql> revoke insert on db.* from 'role_test'; Query OK, 0 rows affected (0.10 sec) # 查看默认角色信息 mysql> select * from mysql.default_roles; +------+-----------+-------------------+-------------------+ | HOST | USER | DEFAULT_ROLE_HOST | DEFAULT_ROLE_USER | +------+-----------+-------------------+-------------------+ | % | read_user | % | role_test | +------+-----------+-------------------+-------------------+ 1 row in set (0.00 sec) # 查看角色与用户关系 mysql> select * from mysql.role_edges; +-----------+-----------+---------+-----------+-------------------+ | FROM_HOST | FROM_USER | TO_HOST | TO_USER | WITH_ADMIN_OPTION | +-----------+-----------+---------+-----------+-------------------+ | % | role_test | % | read_user | N | +-----------+-----------+---------+-----------+-------------------+ 1 row in set (0.00 sec) # 删除角色 mysql> drop role role_test; Query OK, 0 rows affected (0.06 sec)
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!