MySQL现在支持创建和管理资源组,并允许将在服务器内运行的线程分配给特定的组,以使线程根据该组可用的资源执行。通过组属性,可以对其资源进行控制,从而允许或限制组中线程的资源消耗。数据库管理员可以根据不同的工作负载适当地修改这些属性。目前,CPU时间是一种可管理的资源,以“虚拟CPU”概念表示,其中包括CPU核心、超线程、硬件线程等。服务器在启动时确定有多少个虚拟CPU可用,具有适当权限的数据库管理员可以将这些CPU与资源组关联,并将线程分配给组。
表加密现在可以通过定义和强制加密默认值来进行全局管理。default_table_encryption变量定义了新创建的模式和通用表空间的加密默认值。还可以使用DEFAULT ENCRYPTION子句在创建模式时定义模式的加密默认值。默认情况下,表继承所创建的模式或通用表空间的加密设置。通过启用table_encryption_privilege_check变量来强制执行加密默认值。当创建或修改一个加密设置与default_table_encryption设置不同的模式或通用表空间时,或者创建或修改一个加密设置与默认模式加密不同的表时,将进行权限检查。当启用table_encryption_privilege_check时,TABLE_ENCRYPTION_ADMIN特权允许覆盖默认的加密设置。
CREATE UNDO TABLESPACE tablespace_name ADD DATAFILE 'file_name.ibu';
使用DROP UNDO TABLESPACE语法可以在运行时删除使用CREATE UNDO TABLESPACE语法创建的撤销表空间。
DROP UNDO TABLESPACE tablespace_name;
ALTER UNDO TABLESPACE语法可以用于将撤销表空间标记为活跃或非活跃状态。
ALTER UNDO TABLESPACE tablespace_name SET {ACTIVE|INACTIVE};
在Information Schema的INNODB_TABLESPACES表中添加了一个STATE列,用于显示表空间的状态。在删除一个撤销表空间之前,它必须处于空状态。
默认情况下,innodb_undo_log_truncate变量是启用的。
innodb_rollback_segments变量定义了每个撤销表空间的回滚段数量。之前,innodb_rollback_segments指定了MySQL实例的总回滚段数。此更改增加了可用于并发事务的回滚段数。更多的回滚段增加了并发事务使用独立回滚段的可能性,从而减少了资源争用。
在除全局临时表空间和撤销表空间文件之外的所有InnoDB表空间文件中都存在序列化字典信息(SDI)。SDI是用于表和表空间对象的序列化元数据。SDI数据的存在提供了元数据冗余性。例如,如果数据字典变得不可用,可以从表空间文件中提取字典对象的元数据。SDI提取是使用ibd2sdi工具进行的。SDI数据以JSON格式存储。
将SDI数据包含在表空间文件中会增加表空间文件的大小。一个SDI记录需要一个索引页,默认大小为16KB。然而,存储时会对SDI数据进行压缩,以减小存储占用空间。
现在,InnoDB存储引擎支持原子DDL(原子数据定义语言)操作。这确保了在DDL操作过程中,即使服务器在操作期间停止,DDL操作也要么完全提交,要么完全回滚。
使用innodb_directories选项,可以在服务器离线时将表空间文件移动或恢复到新位置。
以下重做日志记录优化已经实施:
现在,用户线程可以在不同步写入的情况下并发地写入日志缓冲区。
现在,用户线程可以以放松的顺序将脏页添加到刷新列表中。
现在,有一个专用的日志线程负责将日志缓冲区中的数据写入系统缓冲区,将系统缓冲区刷新到磁盘,通知用户线程已写入和已刷新的重做日志内容,维护放松刷新列表顺序所需的延迟,并进行写入检查点操作。
新添加了系统变量来配置用户线程等待已刷新的重做时使用的自旋延迟:
innodb_log_wait_for_flush_spin_hwm:定义了日志刷新的最大平均时间,超过这个时间后,用户线程在等待已刷新的重做时将不再进行自旋。
innodb_log_spin_cpu_abs_lwm:定义了在等待已刷新的重做期间,用户线程停止自旋的最低CPU使用率。
innodb_log_spin_cpu_pct_hwm:定义了在等待已刷新的重做期间,用户线程停止自旋的最高CPU使用率。
从MySQL 8.0.12版本开始,支持在以下ALTER TABLE操作中使用ALGORITHM=INSTANT:
- 添加列(Instant ADD COLUMN)。这个特性也被称为“即时添加列”。
- 添加或删除虚拟列。
- 添加或删除列的默认值。
- 修改ENUM或SET列的定义。
- 更改索引类型。
- 重命名表。
支持ALGORITHM=INSTANT的操作只修改数据字典中的元数据。不会对表进行元数据锁定,并且表数据不受影响,使得操作瞬间完成。如果没有显式指定,支持ALGORITHM=INSTANT的操作默认会使用该选项。如果指定了ALGORITHM=INSTANT但不支持的话,操作将立即失败并报错。
从MySQL 8.0.13版本开始,TempTable存储引擎支持存储二进制大对象(BLOB)类型的列。这个改进提高了使用包含BLOB数据的临时表的查询性能。之前,包含BLOB数据的临时表是存储在由internal_tmp_disk_storage_engine定义的磁盘存储引擎中的。
从MySQL 8.0.13版本开始,InnoDB的数据静止加密功能支持通用表空间。以前,只能对每个表创建文件表空间进行加密。为了支持通用表空间的加密,CREATE TABLESPACE和ALTER TABLESPACE语法进行了扩展,增加了ENCRYPTION子句。
现在,Information Schema中的INNODB_TABLESPACES表包含一个ENCRYPTION列,指示表空间是否被加密。
还添加了stage/innodb/alter tablespace (encryption)性能模式阶段仪表,以便监控通用表空间加密操作。
innodb_buffer_pool_in_core_file
变量可以通过排除InnoDB缓冲池页面来减少核心文件的大小。为了使用这个变量,必须启用 core_file
变量,并且操作系统必须支持 madvise()
的非POSIX扩展 MADV_DONTDUMP
,该扩展在Linux 3.4及更高版本中支持。从MySQL 8.0.13版本开始,用户创建的临时表和由优化器创建的内部临时表存储在会话临时表空间中,该空间从一个临时表空间池中为会话分配。当一个会话断开连接时,它的临时表空间将被截断并释放回空间池。在之前的版本中,临时表被创建在全局临时表空间(ibtmp1)中,这个表空间在临时表被删除后不会将磁盘空间归还给操作系统。
innodb_temp_tablespaces_dir变量定义了会话临时表空间的创建位置,默认位置是数据目录中的 #innodb_temp目录。可以通过修改这个变量来设置会话临时表空间的存储位置。同时,INNODB_SESSION_TEMP_TABLESPACES表提供有关会话临时表空间的元数据。
全局临时表空间(ibtmp1)现在存储对用户创建的临时表所做的更改的回滚段。
从MySQL 8.0.14版本开始,InnoDB支持并行聚簇索引读取,这可以提高CHECK TABLE性能。这个功能不适用于二级索引扫描。要实现并行聚簇索引读取,innodb_parallel_read_threads
会话变量必须被设置为大于1的值。默认值为4。具体用于执行并行聚簇索引读取的线程数量由 innodb_parallel_read_threads
设置或索引子树的数量确定,取两者中较小的那个。
从MySQL 8.0.14版本开始,当启用 innodb_dedicated_server
变量时,根据自动配置的缓冲池大小,调整日志文件的大小和数量。以前,日志文件的大小是根据服务器上检测到的内存量进行配置的,并且日志文件的数量没有自动配置。
从MySQL 8.0.14版本开始,CREATE TABLESPACE语句的ADD DATAFILE子句是可选的,这允许没有FILE特权的用户创建表空间。执行CREATE TABLESPACE语句而没有ADD DATAFILE子句将隐式创建一个具有唯一文件名的表空间数据文件。
默认情况下,当TempTable存储引擎占用的内存超过 temptable_max_ram
变量定义的内存限制时,TempTable存储引擎会开始从磁盘上分配使用内存映射的临时文件。从MySQL 8.0.16版本开始,这个行为由 temptable_use_mmap
变量来控制。禁用 temptable_use_mmap
将导致TempTable存储引擎使用InnoDB存储引擎的磁盘上的内部临时表作为其溢出机制,而不是使用内存映射文件。
从MySQL 8.0.16版本开始,InnoDB的数据静止加密功能支持对mysql系统表空间进行加密。mysql系统表空间包含了mysql系统数据库和MySQL数据字典表。
innodb_spin_wait_pause_multiplier
变量是在MySQL 8.0.16版本中引入的,它可以更好地控制线程在等待获取互斥锁或读写锁时发生的自旋锁轮询延迟的持续时间。可以通过微调延迟来考虑不同处理器架构上的PAUSE指令的执行时间差异。
在MySQL 8.0.17中,通过更好地利用读线程、减少并行扫描期间的预取活动的读线程I/O,并支持对分区进行并行扫描,改进了InnoDB对大型数据集的并行读取线程性能。
通过优化读线程的利用率、减少并行扫描期间的读线程I/O以及支持分区的并行扫描,可以提高InnoDB对大型数据集的并行读取线程性能。
innodb_idle_flush_pct
变量是在MySQL 8.0.18版本中引入的,它允许在空闲期间限制页刷新,这有助于延长固态存储设备的使用寿命。
从MySQL 8.0.19版本开始,支持对InnoDB数据进行高效采样,以生成直方图统计信息。
从MySQL 8.0.20版本开始,双写缓冲区存储区域位于双写文件中。在之前的版本中,存储区域位于系统表空间中。将存储区域迁出系统表空间可以减少写入延迟,增加吞吐量,并提供关于双写缓冲区页放置的灵活性。
以下系统变量是用于高级双写缓冲区配置的:
innodb_doublewrite_dir:定义双写缓冲区文件所在的目录。
innodb_doublewrite_files:定义双写文件的数量。
innodb_doublewrite_pages:定义批量写入的每个线程的最大双写页数。
innodb_doublewrite_batch_size:定义批量写入的双写页数。
MySQL 8.0.20对Contenion-Aware Transaction Scheduling (CATS)算法进行了改进。CATS算法优先处理等待锁的事务,提高了事务调度的性能和准确性。在这个版本中,事务调度权重计算在一个独立的线程中完成,从而提高了计算性能和准确性。
同时,MySQL 8.0.20还移除了之前用于事务调度的First In First Out (FIFO)算法。CATS算法的增强使得FIFO算法变得多余。之前由FIFO算法执行的事务调度现在由CATS算法执行。
为了支持对CATS算法分配的事务调度权重进行查询,INFORMATION_SCHEMA.INNODB_TRX表中添加了一个TRX_SCHEDULE_WEIGHT列。
此外,MySQL 8.0.20还引入了一些用于监控代码级事务调度事件的INNODB_METRICS计数器:
lock_rec_release_attempts:尝试释放记录锁的次数。
lock_rec_grant_attempts:尝试授予记录锁的次数。
lock_schedule_refreshes:在更新事务调度权重时,等待图被分析的次数。
从MySQL 8.0.21开始,为了提高对需要访问表和行资源锁队列的操作的并发性,锁系统互斥锁(lock_sys->mutex)被分片锁取代,并且锁队列被分为表锁和页面锁队列分片,每个分片由一个专用互斥锁保护。以前,单个锁系统互斥锁保护所有锁队列,这在高并发系统中是一个争用点。新的分片实现允许更细粒度地访问锁队列。
锁系统互斥锁(lock_sys->mutex)被以下分片锁所替代:
全局锁(lock_sys->latches.global_latch),由64个读写锁对象(rw_lock_t)组成。访问单个锁队列需要共享全局锁和锁队列分片的锁。需要访问所有锁队列的操作需要获取一个独占的全局锁,该锁会锁定所有表锁和页面锁队列分片。
表锁分片锁(lock_sys->latches.table_shards.mutexes),由512个互斥锁组成的数组,每个互斥锁专用于512个表锁队列分片之一。
页面锁分片锁(lock_sys->latches.page_shards.mutexes),由512个互斥锁组成的数组,每个互斥锁专用于512个页面锁队列分片之一。
监控旧的锁系统互斥锁的Performance Schema wait/synch/mutex/innodb/lock_mutex工具已被用于监控新的全局、表锁和页面锁分片锁的工具所替代:
wait/synch/sxlock/innodb/lock_sys_global_rw_lock
wait/synch/mutex/innodb/lock_sys_table_mutex
wait/synch/mutex/innodb/lock_sys_page_mutex
从MySQL 8.0.21开始,使用DATA DIRECTORY子句在数据目录外创建的表和分区表数据文件被限制为InnoDB已知的目录。这个改变允许数据库管理员控制表空间数据文件的创建位置,并确保在恢复期间可以找到这些数据文件。
通用和按表单独存储的表空间数据文件(.ibd文件)不能再在undo表空间目录(innodb_undo_directory)中创建,除非该目录被InnoDB所知。
被InnoDB所知的目录是由datadir、innodb_data_home_dir和innodb_directories变量定义的目录。
对于属于按表单独存储的表空间的InnoDB表进行截断操作将删除现有的表空间并创建一个新的表空间。从MySQL 8.0.21开始,如果当前表空间目录是未知的,InnoDB会在默认位置创建新的表空间,并在错误日志中写入警告。如果希望TRUNCATE TABLE在当前位置创建表空间,请在运行TRUNCATE TABLE之前将该目录添加到innodb_directories设置中。
从MySQL 8.0.21开始,可以使用ALTER INSTANCE {ENABLE|DISABLE} INNODB REDO_LOG语法来启用和禁用重做日志记录。这个功能旨在加载数据到一个新的MySQL实例中。禁用重做日志记录可以通过避免重做日志写入来加快数据加载速度。
新增的INNODB_REDO_LOG_ENABLE权限允许启用和禁用重做日志记录。
新增的Innodb_redo_log_enabled状态变量允许监视重做日志记录状态。可以使用该状态变量查看是否已经启用或禁用了重做日志记录。
在启动时,InnoDB会根据数据字典中存储的表空间文件路径验证已知表空间文件的路径,以防止表空间文件被移动到其他位置。MySQL 8.0.21引入的新变量innodb_validate_tablespace_paths允许禁用表空间路径验证。该功能适用于表空间文件不会被移动的环境。禁用表空间路径验证可以提高在具有大量表空间文件的系统上的启动时间。
从MySQL 8.0.21开始,当使用行级复制时,在支持原子DDL的存储引擎上使用CREATE TABLE ... SELECT语句将作为一个事务记录在二进制日志中。以前,它被记录为两个事务,一个用于创建表,另一个用于插入数据。通过这个改变,CREATE TABLE ... SELECT语句现在对于行级复制是安全的,并允许与基于GTID的复制一起使用。
在繁忙的系统上截断undo表空间可能会影响性能,因为与此操作相关的刷新操作会将旧的undo表空间页面从缓冲池中移除并将新的undo表空间的初始页面刷新到磁盘上。为了解决这个问题,从MySQL 8.0.21开始,刷新操作被移除了。
旧的undo表空间页面在不再使用时被被动地释放,或者在下一个全量检查点时被移除。现在,截断操作期间新的undo表空间的初始页面被记录在重做日志中,而不是刷新到磁盘上,这也提高了undo表空间截断操作的耐久性。
为了避免由过多的undo表空间截断操作引起的潜在问题,现在在检查点之间对同一个undo表空间的截断操作被限制为64次。如果超过了这个限制,undo表空间仍然可以被设置为非活动状态,但直到下一个检查点之后才会被截断。
与已删除的undo截断刷新操作相关的INNODB_METRICS计数器也被移除了。被移除的计数器包括:undo_truncate_sweep_count、undo_truncate_sweep_usec、undo_truncate_flush_count和undo_truncate_flush_usec。
从MySQL 8.0.22开始,新的innodb_extend_and_initialize变量允许在Linux上配置InnoDB如何为每个表和通用表空间分配空间。默认情况下,当一个操作需要在表空间中分配额外的空间时,InnoDB会为表空间分配页面,并在这些页面上实际写入NULL值。如果频繁地分配新页面,这种行为会影响性能。您可以在Linux系统上禁用innodb_extend_and_initialize,以避免在新分配的表空间页面上实际写入NULL值。当禁用innodb_extend_and_initialize时,空间分配使用posix_fallocate()调用进行,这些调用会保留空间但不实际写入NULL值。
posix_fallocate()操作不是原子操作,这意味着在将空间分配给表空间文件并更新文件元数据之间可能发生故障。这种故障可能会导致新分配的页面处于未初始化状态,从而在InnoDB尝试访问这些页面时导致失败。为了防止出现这种情况,InnoDB在分配新的表空间页面之前写入重做日志记录。如果页分配操作被中断,通过重做日志记录进行恢复时会重新执行该操作。
从MySQL 8.0.23开始,InnoDB支持对属于加密表空间的双写文件页面进行加密。这些页面使用关联表空间的加密密钥进行加密。
在MySQL 8.0.23中引入的temptable_max_mmap变量定义了TempTable存储引擎允许从内存映射(MMAP)文件中分配的最大内存量,然后开始将内部临时表数据存储在磁盘上。设置为0会禁用从MMAP文件中分配内存。
在MySQL 8.0.23中引入的AUTOEXTEND_SIZE选项定义了当InnoDB表空间已满时,InnoDB扩展表空间的大小的量,从而可以以较大的增量扩展表空间大小。AUTOEXTEND_SIZE选项可用于CREATE TABLE、ALTER TABLE、CREATE TABLESPACE和ALTER TABLESPACE语句。
在Information Schema的INNODB_TABLESPACES表中添加了一个AUTOEXTEND_SIZE列。
在MySQL 8.0.26中引入的innodb_segment_reserve_factor系统变量允许配置作为空页保留的表空间文件段页面的百分比。
在支持fdatasync()系统调用的平台上,innodb_use_fdatasync变量允许在操作系统刷新时使用fdatasync()而不是fsync()。fdatasync()系统调用只有在必要时才会刷新文件元数据,以提供潜在的性能优势。
从MySQL 8.0.28开始,tmp_table_size变量定义了由TempTable存储引擎创建的任何单个内存中的内部临时表的最大大小。适当的大小限制可以防止单个查询消耗过多的全局TempTable资源。
从MySQL 8.0.28开始,innodb_open_files变量定义了InnoDB在一次可以打开的文件数,可以使用SELECT innodb_set_open_files_limit(N)语句在运行时设置。该语句执行一个存储过程来设置新的限制。
为了防止非LRU管理的文件消耗整个innodb_open_files限制,非LRU管理的文件被限制在innodb_open_files限制的90%,其中留出10%的innodb_open_files限制给LRU管理的文件。
innodb_open_files限制包括临时表空间文件,在先前不计入限制。
从MySQL 8.0.28开始,InnoDB支持使用ALGORITHM=INSTANT执行ALTER TABLE ... RENAME COLUMN操作。
从MySQL 8.0.29开始,InnoDB支持使用ALGORITHM=INSTANT执行ALTER TABLE ... DROP COLUMN操作。
在此之前的版本中,只能将即时添加的列添加为表的最后一列。从MySQL 8.0.29开始,即时添加的列可以添加到表中的任何位置。
使用ALGORITHM=INSTANT选项执行ALTER TABLE ... DROP COLUMN操作时,InnoDB引擎将创建受影响行的新版本,而不是立即删除该列。它会在表数据的基础上创建一个新的表定义,并且会保留之前版本的行用于回滚和查询历史数据。最多可以保留64个行版本。
从MySQL 8.0.30开始,innodb_doublewrite系统变量支持DETECT_ONLY和DETECT_AND_RECOVER两种设置。
使用DETECT_ONLY设置时,数据库页面内容不会写入doublewrite缓冲区,并且恢复过程不会使用doublewrite缓冲区来修复不完整的页面写入。这个轻量级的设置仅用于检测不完整的页面写入。它可以在一些特定情况下提高性能,但也增加了数据损坏的风险。如果发生断电或崩溃,可能需要进行额外的恢复操作。
DETECT_AND_RECOVER设置与已有的ON设置等效,即数据库页面内容将写入doublewrite缓冲区,并且恢复过程将使用doublewrite缓冲区来确保数据的一致性。
从MySQL 8.0.30开始,InnoDB支持动态配置重做日志容量。可以在运行时设置innodb_redo_log_capacity系统变量来增加或减少重做日志文件占用的总磁盘空间。
随着这个改变,重做日志文件的数量和默认位置也发生了变化。从MySQL 8.0.30开始,InnoDB在数据目录的#innodb_redo目录中维护32个重做日志文件。之前,InnoDB默认在数据目录中创建两个重做日志文件,重做日志文件的数量和大小由innodb_log_files_in_group和innodb_log_file_size变量控制。这两个变量现在已被弃用。
如果定义了innodb_redo_log_capacity设置,则会忽略innodb_log_files_in_group和innodb_log_file_size设置;否则,这些设置将用于计算innodb_redo_log_capacity设置(innodb_log_files_in_group * innodb_log_file_size = innodb_redo_log_capacity)。如果这些变量都没有设置,则重做日志容量将设置为innodb_redo_log_capacity的默认值,即104857600字节(100MB)。
还提供了几个状态变量用于监控重做日志和重做日志调整操作。
在MySQL 8.0.31中,引入了两个新的状态变量,用于监控在线缓冲池调整操作。Innodb_buffer_pool_resize_status_code状态变量报告一个状态代码,表示在线缓冲池调整操作的阶段。Innodb_buffer_pool_resize_status_progress状态变量报告一个百分比值,表示每个阶段的进度。