• [技术干货] mysql怎样查询被锁的表
    方法:1、利用“show OPEN TABLES where In_use > 0;”命令查看表被锁状态;2、利用“SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS”命令查询被锁的表。本教程操作环境:windows10系统、mysql8.0.22版本、Dell G3电脑。mysql怎样查询被锁的表1.查看表是否被锁:(1)直接在mysql命令行执行:show engine innodb status\G。(2)查看造成死锁的sql语句,分析索引情况,然后优化sql。(3)然后show processlist,查看造成死锁占用时间长的sql语句。(4)show status like ‘%lock%。2.查看表被锁状态和结束死锁步骤:(1)查看表被锁状态:show OPEN TABLES where In_use > 0; 这个语句记录当前锁表状态 。(2)查询进程:show processlist查询表被锁进程;查询到相应进程killid。(3)分析锁表的SQL:分析相应SQL,给表加索引,常用字段加索引,表关联字段加索引。(4)查看正在锁的事物:SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS。(5)查看等待锁的事物:SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS。扩展资料MySQL锁定状态查看命令:Checking table:正在检查数据表(这是自动的)。Closing tables:正在将表中修改的数据刷新到磁盘中,同时正在关闭已经用完的表。这是一个很快的操作,如果不是这样的话,就应该确认磁盘空间是否已经满了或者磁盘是否正处于重负中。Connect Out:复制从服务器正在连接主服务器。Copying to tmp table on disk:由于临时结果集大于tmp_table_size,正在将临时表从内存存储转为磁盘存储以此节省内存。Creating tmp table:正在创建临时表以存放部分查询结果。deleting from main table:服务器正在执行多表删除中的第一部分,刚删除第一个表。deleting from reference tables:服务器正在执行多表删除中的第二部分,正在删除其他表的记录。Flushing tables:正在执行FLUSH TABLES,等待其他线程关闭数据表。Killed:发送了一个kill请求给某线程,那么这个线程将会检查kill标志位,同时会放弃下一个kill请求。MySQL会在每次的主循环中检查kill标志位,不过有些情况下该线程可能会过一小段才能死掉。如果该线程程被其他线程锁住了,那么kill请求会在锁释放时马上生效。Locked:被其他查询锁住了。Sending data:正在处理SELECT查询的记录,同时正在把结果发送给客户端。Sorting for group:正在为GROUP BY做排序。Sorting for order:正在为ORDER BY做排序。Opening tables:这个过程应该会很快,除非受到其他因素的干扰。例如,在执ALTER TABLE或LOCK TABLE语句行完以前,数据表无法被其他线程打开。正尝试打开一个表。Removing duplicates:正在执行一个SELECT DISTINCT方式的查询,但是MySQL无法在前一个阶段优化掉那些重复的记录。因此,MySQL需要再次去掉重复的记录,然后再把结果发送给客户端。Reopen table:获得了对一个表的锁,但是必须在表结构修改之后才能获得这个锁。已经释放锁,关闭数据表,正尝试重新打开数据表。Repair by sorting:修复指令正在排序以创建索引。Repair with keycache:修复指令正在利用索引缓存一个一个地创建新索引。它会比Repair by sorting慢些。Searching rows for update:正在讲符合条件的记录找出来以备更新。它必须在UPDATE要修改相关的记录之前就完成了。Sleeping:正在等待客户端发送新请求。System lock:正在等待取得一个外部的系统锁。如果当前没有运行多个mysqld服务器同时请求同一个表,那么可以通过增加--skip-external-locking参数来禁止外部系统锁。Upgrading lock:INSERT DELAYED正在尝试取得一个锁表以插入新记录。Updating:正在搜索匹配的记录,并且修改它们。User Lock:正在等待GET_LOCK()。Waiting for tables:该线程得到通知,数据表结构已经被修改了,需要重新打开数据表以取得新的结构。然后,为了能的重新打开数据表,必须等到所有其他线程关闭这个表。waiting for handler insert:INSERT DELAYED已经处理完了所有待处理的插入操作,正在等待新的请求。原文链接:https://m.php.cn/article/487451.html
  • [技术干货] mysql表被锁了怎么办?
    mysql表被锁了的解决办法:1、通过暴力解决方式,即重启MYSQ;2、通过“show processlist;”命令查看表情况;3、通过“KILL10866;”命令kill掉锁表的进程ID。mysql表被锁了的解决办法如下:1、暴力解决方式重启MYSQL(重启解决问题利器,手动滑稽)2、查看表情况:1show processlist;1State状态为Locked即被其他查询锁住3、kill掉锁表的进程ID1KILL   10866;//后面的数字即时进程的ID原文链接:https://m.php.cn/article/418327.html
  • [技术干货] Ubuntu卸载mysql
    Ubuntu卸载mysql删除mysql的配置文件sudo rm /var/lib/mysql/ -Rsudo rm /etc/mysql/ -R自动卸载mysql(包括server和client)sudo apt-get autoremove mysql* --purge输入y选择yes,按回车键sudo apt-get remove apparmor输入y,按回车键然后在终端中查看MySQL的依赖项dpkg --list|grep mysql依次输入下面的命令1sudo apt-get remove dbconfig-mysqlsudo apt-get remove mysql-clientsudo apt-get remove mysql-client-5.7sudo apt-get remove mysql-client-core-5.7再次执行自动卸载sudo apt-get autoremove mysql* --purge查看MySQL的剩余依赖项dpkg --list|grep mysql如果显示为空,则证明mysql完全删除
  • [问题求助] 求助:在进行鲲鹏云上应用高可用部署时登录MySQL进入命令行却闪退,报错段错误segment fault,且登陆时警告磁盘上的单元文件、源配置文件或 mysql.service 的插入项已更改。按提示操作没有作用
    背景环境鲲鹏云上应用高可用部署实验 系统:openEuler 20.03 64bit with ARM 版本:mysql-boost-8.0.24 流程:利用cmake编译mysql最终安装报错1.段错误segment fault2.启动时警告,磁盘上的单元文件、源配置文件或 mysql.service 的插入项已更改,但是输入systemctl daemon-reload没有任何作用3.查看messages文件时显示return code=[139], execute failed by [root(uid=0)] from [pts/0 (59.172.176.230)]报错图像
  • [技术干货] MySQL索引知多少
    索引及其作用 索引(Index)是帮助 MySQL 高效获取数据的数据结构。索引的本质是数据结构。索引作用是帮助 MySQL 高效获取数据。通俗的说,索引就像一本书的目录,通过目录去找想看的章节就很快,索引也是一样的。如果没有索引,MySQL在查询数据的时候就需要从第一行数据开始一行一行数据对比,只能扫描完整个表找到要查询的数据,表的数据越多需要花费的时间越多。如果表中有相关列的索引,MySQL可以快速确定在数据文件中间查找的位置,而无需查看所有数据,这比按顺序读取每一行要快得多。索引常用的数据结构有BTREE、HASH、RTREE等等,其中数BTREE最为常见。索引的分类 索引分为聚集索引和二级索引。聚集索引 InnoDB引擎中使用了聚集索引(Clustered index),就是将表的主键用来构造一棵B+树,并且将整张表的行记录数据存放在该 B+树的叶子节点中。也就是所谓的索引即数据,数据即索引。由于聚集索引是利用表的主键构建的,所以每张表只能拥有一个聚集索引。一般来说,在MySQL中聚集索引和主键是一个意思。聚集索引的叶子节点就是数据页。换句话说,数据页上存放的是完整的每行记录。因此聚集索引的一个优点就是:通过过聚集索引能获取完整的整行数据。另一个优点是:对于主键的排序查找和范围查找速度非常快。如果没有设置主键的话,MySQL默认会创建一个隐含列row_id作为主键。二级索引 二级索引(Secondary Index,也称辅助索引、非聚集索引)是InnoDB引擎中的一类索引,聚集索引以外的索引统称为二级索引,包括唯一索引、联合索引、全文索引等等。二级索引并不包含行记录的全部数据,二级索引上除了当前列以外还包含一个主键,通过这个主键来查询聚集索引上对应的数据。当查询除索引以外的其他数据时,由于数据不在索引上就需要通过主键来找到完整的行记录,这就是回表。针对二级索引MySQL提供了一个优化技术,索引覆盖(covering index)。即从辅助索引中就可以得到查询的记录,就不需要回表再根据聚集索引查询一次完整记录。使用索引覆盖的一个好处是辅助索引不包含整行记录的所有信息,故其大小要远小于聚集索引,因此可以减少大量的IO操作,但是前提是要查询的所有列必须都加了索引。唯一索引 唯一索引(Unique Index)要求列的数据必须是唯一的,唯一索引具有唯一性约束,在插入数据时,如果有列中有相同的数据就会报错。唯一索引可以允许多个列的值为NULL,如果列是字符串类型的话,空字符串值只能有一个。全文索引 全文索引(Full-Text Index)只有在MyISAM和InnoDB存储引擎中支持,全文索引只能创建在基于文本的列上,例如CHAR、VARCHAR、TEXT类型。全文索引不支持索引前缀,即使设置了索引前缀也不会起作用。全文索引采用的是倒排索引(inverted index)设计,倒排索引就是将文档中包含的关键字全部提取处理,然后再将关键字和文档之间的对应关系保存起来,最后再对关键字本身做索引排序。用户在检索某一个关键字时,先对关键字的索引进行查找,再通过关键字与文档的对应关系找到所在文档。为了支持邻近搜索,还存储每个单词的位置信息,作为字节偏移量。MySQL 从设计之初就是关系型数据库,存储引擎虽然支持全文检索,整体架构上对全文检索支持并不好而且限制很多,比如每张表只能有一个全文检索的索引,不支持没有单词界定符(delimiter)的语言,如中文、日语、韩语等。全文索引辅助表创建一个db_test数据库,并创建一个users表,users表结构如下在name字段上创建全文索引:ALTER TABLE `users` ADD FULLTEXT INDEX `idx_name` (`name`);然后查看INNODB_SYS_TABLES中db_test数据库信息SELECT table_id, name, space from INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name LIKE 'db_test/%';当全文索引创建时就会创建一组辅助索引表,前六个表就是辅助索引表。辅助索引表以 FTS_ 开头,以index_# 结尾,每个辅助索引表的表名都和全文索引所在表的table_id的十六进制值关联。比如db_test/users的table_id是170,170对应的十六进制是0xaa,辅助索引表的表名就用aa作为其表名的一部分,以便和db_test/users表关联。全文索引的index_id也可以通过辅助索引表的表名获取,拿第一个辅助索引表db_test/FTS_00000000000000aa_00000000000000fb_INDEX_1举例,fb就是index_id的十六进制表示,换算成十进制是251,所以index_id=251.可通过以下SQL语句验证index_id:SELECT index_id, name, table_id, space from INFORMATION_SCHEMA.INNODB_SYS_INDEXES WHERE index_id = 251;db_test/users表的table_id=170,通过index_id = 251查询到的table_id也是170,并且索引名称也是我们创建的idx_name,所以这个index_id就是我们创建的全文索引的id。多列索引 多列索引(Multiple-Column Index,又称联合索引、复合索引)顾名思义就是几个列共同组成一个索引。多列索引最多由16个列组成。多列索引遵守最左前缀原则。最左前缀原则就是在查询数据时,以最左边的列为基准进行索引匹配。例如,有个索引mul_index(col1, col2, col3),在进行索引查询的时候,只有(col1)、(col1, col2)和(col1, col2, col3)这三种组合才能使多列索引mul_index(col1, col2, col3)生效。就是说col1只能在查询时被用到,这个索引就能被用到,索引在创建多列索引时一定要将查询最频繁的列放到最左边。空间索引 MyISAM、InnoDB、NDB和ARCHIVE存储引擎都支持空间索引(Spatial Indexe),但是要求列必须是POINT和GEOMETRY相关类型。但是,对空间列索引的支持因引擎而异,可根据以下规则使用空间列上的空间和非空间索引。1.空间索引在空间列上有以下特性:只有MyISAM和InnoDB可以使用,如果在创建时指定其他存储引擎会报错索引列必须是NOT NULL不允许使用索引前缀2.非空间索引在空间列上有以下特性:允许用于除ARCHIVE存储引擎之外的任何支持空间列的存储引擎。列值可以为NULL,除非是唯一索引。非空间索引在空间列时,除了列的类型是POINT之外,在创建索引的时候都要指定索引前缀并且索引前缀长度是以字节为单位的。非空间索引在空间列的数据结构取决于存储引擎,目前使用的是BTREE。在InnoDB、MyISAM和 MEMORY存储引擎中允许空间列的值为NULL。空间索引主要用于列类型是地理位置或者坐标之类的列上的,空间索引主要使用的是R-Tree。自适应哈希索引 自适应哈希索引(Adaptive Hash Index)是InnoDB表的优化,可以通过在内存中构造哈希索引来加速使用 = 和 IN 运算符的查找。InnoDB 存储引擎内部自己去监控索引表,如果监控到某个索引频繁使用,那么就认为是热数据,然后内部就会自动创建一个 hash 索引。从某种意义上说,自适应哈希索引在运行时对MySQL进行配置,以利用充足的主存,这样更接近主存数据库的架构。这个特性是由innodb_adaptive_hash_index参数控制的,默认是开启的。可以通过以下命令查看自适应hash索引的使用状况show engine innodb statusstatus字段内容很长,有兴趣的可以自己试试看下,里面有这么一段:-------------------------------------INSERT BUFFER AND ADAPTIVE HASH INDEX-------------------------------------Ibuf: size 1, free list len 195, seg size 197, 0 mergesmerged operations: insert 0, delete mark 0, delete 0discarded operations: insert 0, delete mark 0, delete 0Hash table size 2267, node heap has 0 buffer(s)Hash table size 2267, node heap has 2 buffer(s)Hash table size 2267, node heap has 0 buffer(s)Hash table size 2267, node heap has 1 buffer(s)Hash table size 2267, node heap has 0 buffer(s)Hash table size 2267, node heap has 1 buffer(s)Hash table size 2267, node heap has 0 buffer(s)Hash table size 2267, node heap has 1 buffer(s)0.00 hash searches/s, 0.00 non-hash searches/s通过 hash searches: nonhash searches 可以大概了解使用哈希索引后的效率。索引的增删改查 新增索引 新增索引有三种方式:使用create index 语句使用alter 语句在CREATE TABLE的时候创建索引前两种方式都是在创建好表以后再给表新增索引的,第三种是在创建表的同时创建索引CREATE TABLE 创建索引 例如:CREATE TABLE `test` (`id` int NOT NULL AUTO_INCREMENT ,`name` varchar(255) NULL ,PRIMARY KEY (`id`),INDEX `idx` (`name`) )CREATE INDEX 创建索引语法:CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name [index_type] ON tbl_name (key_part,...) [index_option] [algorithm_option | lock_option] ...key_part: col_name [(length)] [ASC | DESC]index_option: { KEY_BLOCK_SIZE [=] value | index_type | WITH PARSER parser_name | COMMENT 'string'}index_type: USING {BTREE | HASH}algorithm_option: ALGORITHM [=] {DEFAULT | INPLACE | COPY}lock_option: LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}带中括号[]的都是可选项,可写可不写,[=]表示等于号可要可不要key_part:col_name [(length)] [ASC | DESC] :表示列名、索引前缀长度、升序或降序index_type:表示使用BTREE或HASH作为索引的数据结构index_option:索引的可选项,包括索引类型、备注、PARSER、KEY_BLOCK_SIZE 等algorithm_option:算法的选择,可选值为DEFAULT、INPLACE、COPYlock_option:锁的选择,可选值为DEFAULT、NONE、SHARED(共享锁)、EXCLUSIVE(排它锁)示例:CREATE INDEX index_name USING BTREE ON account(amount DESC) COMMENT 'string' ALGORITHM INPLACE LOCK SHARED;ALTER TABLE 创建索引 语法:ALTER TABLE tbl_name ADD {UNIQUE | FULLTEXT | SPATIAL} INDEX index_name(key_part,...) [index_option]index_option: { KEY_BLOCK_SIZE [=] value | index_type | WITH PARSER parser_name | COMMENT 'string'示例:-- 添加唯一索引ALTER TABLE `account` ADD UNIQUE INDEX `uk` (`amount`) USING BTREE;ALTER TABLE 和 CREATE INDEX 创建索引的区别:ALTER 本身有修改的意思,所以可以对索引进行增删改,而CREATE只能创建索引CREATE不能创建主键,ALTER可以CREATE INDEX 可以指定索引算法ALGORITHM和LOCK,ALTER在添加索引的时候不能指定。修改索引 修改索引是先删除之前的索引,然后重新添加ALTER TABLE tableName DROP INDEX oldIndexName,ADD INDEX indexName(columns ...) USING BTREE;删除索引 删除索引有两种方式:ALTER TABLE tableName DROP INDEX indexName;或DROP INDEX indexName ON tableName;索引查询 SHOW INDEX FROM tableName;索引前缀 对于字符串类型的索引,在创建索引的时候可以指定以索引的前多少个字符作为索引,可以通过使用col_name(length)语法来指定索引前缀长度,这样可以节省空间和查询效率。索引前缀使用范围及注意事项:可以给类型为CHAR、VARCHAR、BINARY和VARBINARY的列指定前缀。如果给类型是BLOB或者TEXT的列创建索引,必须为其指定前缀。此外,BLOB和TEXT类型的列只能在存储引擎是InnoDB、MyISAM和BLACKHOLE的表上建立索引。索引前缀的长度是以字节为单位的。对于非二进制的(CHAR,VARCHAR,TEXT)的字符类型来说,长度指的是字符的长度。对于二进制的(BINARY, VARBINARY, BLOB)字符类型来说,长度指的是字节的长度。使用多字节的字符编码时,在给二进制的字符类型的列设置长度时要考虑这些。索引前缀长度是否支持或者如何支持取决于存储引擎。对于InnoDB引擎来说,索引前缀长度可以最多可以支持767 bits,如果innodb_large_prefix参数开启,最多能支持3072 bits。对于MyISAM引擎来说,索引前缀的长度被限制在1000 bits以内。对于NDB引擎来说,压根就不支持索引前缀。从 MySQL 5.7.17 开始,如果指定的索引前缀超过最大列数据类型大小,CREATE INDEX会按如下方式处理索引:对于非唯一索引,要么发生错误(如果启用了SQL严格模式),要么索引长度减少到列数据类型大小内并产生警告(如果未启用严格SQL模式)。对于唯一索引,无论SQL模式如何都会发生错误,因为减少索引长度可能会导致插入不满足指定唯一性要求的非唯一条目。如果列的前n(n < 列的数据类型长度)个字符不同,使用索引前缀可能不会比使用整个列做索引慢,而且使用索引前缀索引文件更小,可以省更多磁盘空间并且可能会提高插入时的效率。索引的选择性 索引的选择性是指不重复的索引值(也称为基数,cardinality)和数据表的记录总数(N)的比值,取值范围是1/N到1之间。索引的选择性越高则查询效率越高,因为选择性高的索引可以让MySQL 在查找时过滤掉更多的行。唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。创建索引时要选择索引选择性高的值创建索引。比如有一百条数据,重复的行数有10条,那么索引的选择性就是10/100,也就是0.1。索引的选择性可以通过下列计算方式带入计算:SELECT COUNT(DISTINCT col...) / COUNT(*) FROM table_name;索引的代价 索引是把双刃剑,有利有弊。利:方面就是能提高查询效率。弊端主要是两个方面:空间代价:每创建一个就会产生一个索引数据文件占用磁盘空间,索引越多占用的磁盘空间也就越大。时间代价:虽然索引是提高了查询效率,但同时也降低了插入、删除和更新的效率。每次对数据进行增删改操作的同时也是在对索引的更改,索引越多更改时需要花费的时间越多。总结本文只是对索引进行一个简单的介绍。索引是把双刃剑,用的好可以提升系统查询效率,用的不好效率不升反降得不偿失。来源:51cto
  • [技术干货] MySQL DDL执行方式-Online DDL介绍
     1 引言 大家好,今天与大家一起分享一下 mysql DDL执行方式。  一般来说MySQL分为DDL(定义)和DML(操作)。 DDL:Data Definition Language,即数据定义语言,那相关的定义操作就是DDL,包括:新建、修改、删除等;相关的命令有:CREATE,ALTER,DROP,TRUNCATE截断表内容(开发期,还是挺常用的),COMMENT 为数据字典添加备注。 DML:Data Manipulation Language,即数据操作语言,即处理数据库中数据的操作就是DML,包括:选取,插入,更新,删除等;相关的命令有:SELECT,INSERT,UPDATE,DELETE,还有 LOCK TABLE,以及不常用的CALL – 调用一个PL/SQL或Java子程序,EXPLAIN PLAN – 解析分析数据访问路径。 我们可以认为: CREATE,ALTER ,DROP,TRUNCATE,定义相关的命令就是DDL; SELECT,INSERT,UPDATE,DELETE,操作处理数据的命令就是DML; DDL、DML区别: DML操作是可以手动控制事务的开启、提交和回滚的。 DDL操作是隐性提交的,不能rollback,一定要谨慎哦! 日常开发我们对一条DML语句较为熟悉,很多开发人员都了解sql的执行过程,比较熟悉,但是DDL是如何执行的呢,大部分开发人员可能不太关心,也认为没必要了解,都交给DBA吧。 其实不然,了解一些能尽量避开一些ddl的坑,那么下面带大家一起了解一下DDL执行的方式,也算抛砖引玉吧。如有错误,还请各位大佬们指正。  2 概述 在MySQL使用过程中,根据业务的需求对表结构进行变更是个普遍的运维操作,这些称为DDL操作。常见的DDL操作有在表上增加新列或给某个列添加索引。  我们常用的易维平台提供了两种方式可执行DDL,包括MySQL原生在线DDL(online DDL)以及一种第三方工具pt-osc。 下图是执行方式的性能对比及说明: 本文将对DDL的执行工具之Online DDL进行简要介绍及分析,pt-osc会专门再进行介绍。3 介绍 MySQL Online DDL 功能从 5.6 版本开始正式引入,发展到现在的 8.0 版本,经历了多次的调整和完善。其实早在 MySQL 5.5 版本中就加入了 INPLACE DDL 方式,但是因为实现的问题,依然会阻塞 INSERT、UPDATE、DELETE 操作,这也是 MySQL 早期版本长期被吐槽的原因之一。  在MySQL 5.6版本以前,最昂贵的数据库操作之一就是执行DDL语句,特别是ALTER语句,因为在修改表时,MySQL会阻塞整个表的读写操作。例如,对表 A 进行 DDL 的具体过程如下: 按照表 A 的定义新建一个表 B 对表 A 加写锁 在表 B 上执行 DDL 指定的操作 将 A 中的数据拷贝到 B 释放 A 的写锁 删除表 A 将表 B 重命名为 A 在以上 2-4 的过程中,如果表 A 数据量比较大,拷贝到表 B 的过程会消耗大量时间,并占用额外的存储空间。此外,由于 DDL 操作占用了表 A 的写锁,所以表 A 上的 DDL 和 DML 都将阻塞无法提供服务。  如果遇到巨大的表,可能需要几个小时才能执行完成,势必会影响应用程序,因此需要对这些操作进行良好的规划,以避免在高峰时段执行这些更改。对于那些要提供全天候服务(24*7)或维护时间有限的人来说,在大表上执行DDL无疑是一场真正的噩梦。  因此,MySQL官方不断对DDL语句进行增强,自MySQL 5.6 起,开始支持更多的 ALTER TABLE 类型操作来避免数据拷贝,同时支持了在线上 DDL 的过程中不阻塞 DML 操作,真正意义上的实现了 Online DDL,即在执行 DDL 期间允许在不中断数据库服务的情况下执行DML(insert、update、delete)。然而并不是所有的DDL操作都支持在线操作。到了 MySQL 5.7,在 5.6 的基础上又增加了一些新的特性,比如:增加了重命名索引支持,支持了数值类型长度的增大和减小,支持了 VARCHAR 类型的在线增大等。但是基本的实现逻辑和限制条件相比 5.6 并没有大的变化。 4 用法 ALTER TABLE tbl_name ADD PRIMARY KEY (column), ALGORITHM=INPLACE, LOCK=NONE;ALTER 语句中可以指定参数 ALGORITHM 和 LOCK 分别指定 DDL 执行的算法模式和 DDL 期间 DML 的锁控制模式。 ALGORITHM=INPLACE 表示执行DDL的过程中不发生表拷贝,过程中允许并发执行DML(INPLACE不需要像COPY一样占用大量的磁盘I/O和CPU,减少了数据库负载。同时减少了buffer pool的使用,避免 buffer pool 中原有的查询缓存被大量删除而导致的性能问题)。 如果设置 ALGORITHM=COPY,DDL 就会按 MySQL 5.6 之前的方式,采用表拷贝的方式进行,过程中会阻塞所有的DML。另外也可以设置 ALGORITHEM=DAFAULT,让 MySQL 以尽量保证 DML 并发操作的原则选择执行方式。 LOCK=NONE 表示对 DML 操作不加锁,DDL 过程中允许所有的 DML 操作。此外还有 EXCLUSIVE(持有排它锁,阻塞所有的请求,适用于需要尽快完成DDL或者服务库空闲的场景)、SHARED(允许SELECT,但是阻塞INSERT UPDATE DELETE,适用于数据仓库等可以允许数据写入延迟的场景)和 DEFAULT(根据DDL的类型,在保证最大并发的原则下来选择LOCK的取值)。 5 两种算法 第一种 Copy: 按照原表定义创建一个新的临时表; 对原表加写锁(禁止DML,允许select); 在步骤1 建立的临时表执行 DDL; 将原表中的数据 copy 到临时表; 释放原表的写锁; 将原表删除,并将临时表重命名为原表。 从上可见,采用 copy 方式期间需要锁表,禁止DML,因此是非Online的。比如:删除主键、修改列类型、修改字符集,这些操作会导致行记录格式发生变化(无法通过全量 + 增量实现 Online)。 第二种 Inplace: 在原表上进行更改,不需要生成临时表,不需要进行数据copy的过程。根据是否行记录格式,又可分为两类: rebuild:需要重建表(重新组织聚簇索引)。比如 optimize table、添加索引、添加/删除列、修改列 NULL/NOT NULL 属性等; no-rebuild:不需要重建表,只需要修改表的元数据,比如删除索引、修改列名、修改列默认值、修改列自增值等。 对于 rebuild 方式实现 Online 是通过缓存 DDL 期间的 DML,待 DDL 完成之后,将 DML 应用到表上来实现的。例如,执行一个 alter table A engine=InnoDB; 重建表的 DDL 其大致流程如下: 建立一个临时文件,扫描表 A 主键的所有数据页; 用数据页中表 A 的记录生成 B+ 树,存储到临时文件中; 生成临时文件的过程中,将所有对 A 的操作记录在一个日志文件(row log)中; 临时文件生成后,将日志文件中的操作应用到临时文件,得到一个逻辑数据上与表 A 相同的数据文件; 用临时文件替换表 A 的数据文件。 说明:  在 copy 数据到新表期间,在原表上是加的 MDL 读锁(允许 DML,禁止 DDL); 在应用增量期间对原表加 MDL 写锁(禁止 DML 和 DDL); 根据表 A 重建出来的数据是放在 tmp_file 里的,这个临时文件是 InnoDB 在内部创建出来的,整个 DDL 过程都在 InnoDB 内部完成。对于 server 层来说,没有把数据挪动到临时表,是一个原地操作,这就是”inplace”名称的来源。 使用Inplace方式执行的DDL,发生错误或被kill时,需要一定时间的回滚期,执行时间越长,回滚时间越长。 使用Copy方式执行的DDL,需要记录过程中的undo和redo日志,同时会消耗buffer pool的资源,效率较低,优点是可以快速停止。 不过并不是所有的 DDL 操作都能用 INPLACE 的方式执行,具体的支持情况可以在(在线 DDL 操作) 中查看。  官网支持列表:6 执行过程 Online DDL主要包括3个阶段,prepare阶段,ddl执行阶段,commit阶段。下面将主要介绍ddl执行过程中三个阶段的流程。  1)Prepare阶段:初始化阶段会根据存储引擎、用户指定的操作、用户指定的 ALGORITHM 和 LOCK 计算 DDL 过程中允许的并发量,这个过程中会获取一个 shared metadata lock,用来保护表的结构定义。 创建新的临时frm文件(与InnoDB无关)。 持有EXCLUSIVE-MDL锁,禁止读写。 根据alter类型,确定执行方式(copy,online-rebuild,online-norebuild)。假如是Add Index,则选择online-norebuild即INPLACE方式。 更新数据字典的内存对象。 分配row_log对象来记录增量(仅rebuild类型需要)。 生成新的临时ibd文件(仅rebuild类型需要) 。 数据字典上提交事务、释放锁。 注:Row log是一种独占结构,它不是redo log。它以Block的方式管理DML记录的存放,一个Block的大小为由参数innodb_sort_buffer_size控制,默认大小为1M,初始化阶段会申请两个Block。 2)DDL执行阶段:执行期间的 shared metadata lock 保证了不会同时执行其他的 DDL,但 DML 能可以正常执行。 降级EXCLUSIVE-MDL锁,允许读写(copy不可写)。 扫描old_table的聚集索引每一条记录rec。 遍历新表的聚集索引和二级索引,逐一处理。 根据rec构造对应的索引项 将构造索引项插入sort_buffer块排序。 将sort_buffer块更新到新的索引上。 记录ddl执行过程中产生的增量(仅rebuild类型需要) 重放row_log中的操作到新索引上(no-rebuild数据是在原表上更新的)。 重放row_log间产生dml操作append到row_log最后一个Block。 3)Commit阶段:将 shared metadata lock 升级为 exclusive metadata lock,禁止DML,然后删除旧的表定义,提交新的表定义。 当前Block为row_log最后一个时,禁止读写,升级到EXCLUSIVE-MDL锁。 重做row_log中最后一部分增量。 更新innodb的数据字典表。 提交事务(刷事务的redo日志)。 修改统计信息。 rename临时idb文件,frm文件。 变更完成。 Online DDL 过程中占用 exclusive MDL 的步骤执行很快,所以几乎不会阻塞 DML 语句。 不过,在 DDL 执行前或执行时,其他事务可以获取 MDL。由于需要用到 exclusive MDL,所以必须要等到其他占有 metadata lock 的事务提交或回滚后才能执行上面两个涉及到 MDL 的地方。  7 踩坑 前面提到 Online DDL 执行过程中需要获取 MDL,MDL (metadata lock) 是 MySQL 5.5 引入的表级锁,在访问一个表的时候会被自动加上,以保证读写的正确性。当对一个表做 DML 操作的时候,加 MDL 读锁;当做 DDL 操作时候,加 MDL 写锁。  为了在大表执行 DDL 的过程中同时保证 DML 能并发执行,前面使用了 ALGORITHM=INPLACE 的 Online DDL,但这里仍然存在死锁的风险,问题就出在 Online DDL 过程中需要 exclusive MDL 的地方。  例如,Session 1 在事务中执行 SELECT 操作,此时会获取 shared MDL。由于是在事务中执行,所以这个 shared MDL 只有在事务结束后才会被释放。 # Session 1> START TRANSACTION;> SELECT * FROM tbl_name;# 正常执行这时 Session 2 想要执行 DML 操作也只需要获取 shared MDL,仍然可以正常执行。# Session 2> SELECT * FROM tbl_name;# 正常执行但如果 Session 3 想执行 DDL 操作就会阻塞,因为此时 Session 1 已经占用了 shared MDL,而 DDL 的执行需要先获取 exclusive MDL,因此无法正常执行。# Session 3> ALTER TABLE tbl_name ADD COLUMN n INT;# 阻塞通过 show processlist 可以看到 ALTER 操作正在等待 MDL。+----+-----------------+------------------+------+---------+------+---------------------------------+-----------------+| Id | User | Host | db | Command | Time | State | Info |│----+-----------------+------------------+------+---------+------+---------------------------------+-----------------+| 11 | root | 172.17.0.1:53048 | demo | Query | 3 | Waiting for table metadata lock | alter table ... |+----+-----------------+------------------+------+---------+------+---------------------------------+-----------------+由于 exclusive MDL 的获取优先于 shared MDL,后续尝试获取 shared MDL 的操作也将会全部阻塞。# Session 4> SELECT * FROM tbl_name;# 阻塞到这一步,后续无论是 DML 和 DDL 都将阻塞,直到 Session 1 提交或者回滚,Session 1 占用的 shared MDL 被释放,后面的操作才能继续执行。  上面这个问题主要有两个原因: Session 1 中的事务没有及时提交,因此阻塞了 Session 3 的 DDL Session 3 Online DDL 阻塞了后续的 DML 和 DDL 对于问题 1,有些ORM框架默认将用户语句封装成事务执行,如果客户端程序中断退出,还没来得及提交或者回滚事务,就会出现 Session 1 中的情况。那么此时可以在 infomation_schema.innodb_trx 中找出未完成的事务对应的线程,并强制退出。 > SELECT * FROM information_schema.innodb_trx\G*************************** 1. row ***************************trx_id: 421564480355704trx_state: RUNNINGtrx_started: 2022-05-01 014:49:41trx_requested_lock_id: NULLtrx_wait_started: NULLtrx_weight: 0trx_mysql_thread_id: 9trx_query: NULLtrx_operation_state: NULLtrx_tables_in_use: 0trx_tables_locked: 0trx_lock_structs: 0trx_lock_memory_bytes: 1136trx_rows_locked: 0trx_rows_modified: 0trx_concurrency_tickets: 0trx_isolation_level: REPEATABLE READtrx_unique_checks: 1trx_foreign_key_checks: 1trx_last_foreign_key_error: NULLtrx_adaptive_hash_latched: 0trx_adaptive_hash_timeout: 0trx_is_read_only: 0trx_autocommit_non_locking: 0trx_schedule_weight: NULL1 row in set (0.0025 sec)可以看到 Session 1 正在执行的事务对应的 trx_mysql_thread_id 为 9,然后执行 KILL 9 即可中断 Session 1 中的事务。 对于问题 2,在查询很多的情况下,会导致阻塞的 session 迅速增多,对于这种情况,可以先中断 DDL 操作,防止对服务造成过大的影响。也可以尝试在从库上修改表结构后进行主从切换或者使用 pt-osc 等第三方工具。  8 限制 仅适用于InnoDB(语法上它可以与其他存储引擎一起使用,如MyISAM,但MyISAM只允许algorithm = copy,与传统方法相同); 无论使用何种锁(NONE,共享或排它),在开始和结束时都需要一个短暂的时间来锁表(排它锁); 在添加/删除外键时,应该禁用 foreign_key_checks 以避免表复制; 仍然有一些 alter 操作需要 copy 或 lock 表(老方法),有关哪些表更改需要表复制或表锁定,请查看官网; 如果在表上有 ON … CASCADE 或 ON … SET NULL 约束,则在 alter table 语句中不允许LOCK = NONE; Online DDL会被复制到从库(同主库一样,如果 LOCK = NONE,从库也不会加锁),但复制本身将被阻止,因为 alter 在从库以单线程执行,这将导致主从延迟问题。 官方参考资料:https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-limitations.html  9 总结 本次和大家一起了解SQL的DDL、DML及区别,也介绍了Online DDL的执行方式。  目前可用的DDL操作工具包括pt-osc,github的gh-ost,以及MySQL提供的在线修改表结构命令Online DDL。pt-osc和gh-ost均采用拷表方式实现,即创建个空的新表,通过select+insert将旧表中的记录逐次读取并插入到新表中,不同之处在于处理DDL期间业务对表的DML操作。  到了MySQL 8.0 官方也对 DDL 的实现重新进行了设计,其中一个最大的改进是 DDL 操作支持了原子特性。另外,Online DDL 的 ALGORITHM 参数增加了一个新的选项:INSTANT,只需修改数据字典中的元数据,无需拷贝数据也无需重建表,同样也无需加排他 MDL 锁,原表数据也不受影响。整个 DDL 过程几乎是瞬间完成的,也不会阻塞 DML,不过目前8.0的INSTANT使用范围较小,后续再对8.0的INSTANT做详细介绍吧。 来源:51CTO
  • [技术干货] MySQL--GTID是什么
     GTID作用 主从环境中主库的dump线程可以直接通过GTID定位到需要发送的binary log的位置,而不需要指定binary log的文件名和位置,因而切换极为方便。  GTID实际上是由UUID+TID (即transactionId)组成的。其中UUID(即server_uuid) 产生于auto.conf文件(cat /data/mysql/data/auto.cnf),是一个MySQL实例的唯一标识。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增,所以GTID能够保证每个MySQL实例事务的执行(不会重复执行同一个事务,并且会补全没有执行的事务)。GTID在一组复制中,全局唯一。   对于2台主以上的结构优势异常明显,可以在数据不丢失的情况下切换新主。  通过GTID复制,这些在主从成立之前的操作也会被复制到从服务器上,引起复制失败。也就是说通过GTID复制都是从最先开始的事务日志开始,即使这些操作在复制之前执行。比如在server1上执行一些drop、delete的清理操作,接着在server2上执行change的操作,会使得server2也进行server1的清理操作。  直接使用CHANGE MASTER TO MASTER_HOST='xxx', MASTER_AUTO_POSITION命令就可以直接完成failover的工作。  GTID变量和表 gtid_executed 表 是GTID持久化的一个介质,实例重启后所有的内存信息都会丢失,GTID模块初始化需要读取GTID持久化介质。  gtid_executed变量 表示数据库中执行了哪些GTID,它是一个处于内存中的GTID SET。  gtid_purged变量 表示由于删除binary log,已经丢失的GTID event,它是一个处于内存中的GTID set。搭建从库时,通常需要使用set global gtid_purged命令设置本变量,用于表示这个备份已经执行了哪些gtid操作,手动删除binary log 不会更新这个变量。  gtid_executed变量和gtid_purged变量这两个变量分别表示,数据库执行了哪些GTID操作,又有哪些GTID操作由于删除binary log 已经丢失了。 变量更新时机 主库更新时机(1)gtid_executed变量一定是实时更新的。在order commit的flush阶段生成GTID,在commit阶段才计入。(2)mysql.executed表在binary log切换时更新(3)gtid_purged变量在清理binary log时修改,比如purge binary logs 或者超过expire_logs_days的设置后从库更新时机log_slave_updates关闭(1)从库mysql.executed 未开启log_slave_updates情况下,只能通过实时更新mysql.executed表来保存(2)gtid_executed变量实时更新(3)gtid_purged变量实时更新log_slave_updates打开从库mysql.executed 开启log_slave_updates情况下,更新和主库一模一样。通用修改时机gtid_executed 表gtid_executed 表 在执行reset master ,set global gtid_purged命令时设置本表gtid_executed变量gtid_executed变量 reset aster清空本变量,set global gtid_executed命令时设置本变量mysql启动时初始化设置gtid_purged 变量reset master清空本变量set global gtid_purged 设置本变量mysql启动初始化设置GTID模块初始化流程1、获取到server_uuid2、读取mysql.gtid_executed表,但是该表不包含当前binlog的GTID3、读取binlog,先反向扫描,获取最后一个binlog中包含的最新GITD,然后正向扫描,获取第一个binary log中的lost GTID。4、将只在binlog的GTID加入mysql.gtid_executed表和gtid_executed变量。此时mysql.gtid_executed表和gtid_executed变量也正确了5、初始化gtid_purged,扫描到的lost GTID。开启GTID MySQL 5.6 版本,在my.cnf文件中添加:gtid_mode=on (必选) #开启gtid功能log_bin=log-bin=mysql-bin (必选) #开启binlog二进制日志功能log-slave-updates=1 (必选) #也可以将1写为onenforce-gtid-consistency=1 (必选) #也可以将1写为onMySQL 5.7或更高版本,在my.cnf文件中添加:gtid_mode=on (必选)enforce-gtid-consistency=1 (必选)log_bin=mysql-bin (可选) #高可用切换,最好开启该功能log-slave-updates=1 (可选) #高可用切换,最好打开该功能GTID的缺点- 不支持非事务引擎;- 不支持create table ... select 语句复制(主库直接报错);(原理: 会生成两个sql, 一个是DDL创建表SQL, 一个是insert into 插入数据的sql; 由于DDL会导致自动提交, 所以这个sql至少需要两个GTID, 但是GTID模式下, 只能给这个sql生成一个GTID)- 不允许一个SQL同时更新一个事务引擎表和非事务引擎表;- 在一个复制组中,必须要求统一开启GTID或者是关闭GTID;- 开启GTID需要重启 (mysql5.7除外);- 开启GTID后,就不再使用原来的传统复制方式;- 对于create temporary table 和 drop temporary table语句不支持;- 不支持sql_slave_skip_counter;GTID跳过事务的方法 开启GTID以后,无法使用sql_slave_skip_counter跳过事务,因为主库会把从库缺失的GTID,发送给从库,所以skip是没有用的。 为了提前发现问题,在gtid模式下,直接禁止使用set global sql_slave_skip_counter =x。 正确的做法: 通过set gtid_next= 'aaaa'('aaaa'为待跳过的事务),然后执行BIGIN; 接着COMMIT产生一个空事务,占据这个GTID,再START SLAVE,会发现下一条事务的GTID已经执行过,就会跳过这个事务了。如果一个GTID已经执行过,再遇到重复的GTID,从库会直接跳过,可看作GTID执行的幂等性。 因为是通过GTID来进行复制的,也需要跳过这个事务从而继续复制,这个事务可以到主上的binlog里面查看:因为不知道找哪个GTID上出错,所以也不知道如何跳过哪个GTID 1、show slave status里的信息里可以找到在执行Master里的POS:1512、通过mysqlbinlog找到了GTID:3、stop slave;4、set session gtid_next='4e659069-3cd8-11e5-9a49-001c4270714e:1'5、begin; commit;6、SET SESSION GTID_NEXT = AUTOMATIC; #把gtid_next设置回来7、start slave; #开启复制1)对于跳过一个错误,找到无法执行事务的编号,比如是2a09ee6e-645d-11e7-a96c-000c2953a1cb:1-10mysql> stop slave;mysql> set gtid_next='2a09ee6e-645d-11e7-a96c-000c2953a1cb:1-10';mysql> begin;mysql> commit;mysql> set gtid_next='AUTOMATIC';mysql> start slave; 2)上面方法只能跳过一个事务,那么对于一批如何跳过?在主库执行"show master status",看主库执行到了哪里,比如:2a09ee6e-645d-11e7-a96c-000c2953a1cb:1-33,那么操作如下:mysql> stop slave;mysql> reset master;mysql> set global gtid_purged='2a09ee6e-645d-11e7-a96c-000c2953a1cb:1-33';mysql> start slave;如何升级成 GTID replication先介绍几个重要GTID_MODE的参数:GTID_MODE = OFF不产生Normal_GTID,只接受来自master的ANONYMOUS_GTID GTID_MODE = OFF_PERMISSIVE不产生Normal_GTID,可以接受来自master的ANONYMOUS_GTID & Normal_GTID GTID_MODE = ON_PERMISSIVE产生Normal_GTID,可以接受来自master的ANONYMOUS_GTID & Normal_GTID GTID_MODE = ON产生Normal_GTID,只接受来自master的Normal_GTID 归纳总结:1)当master产生Normal_GTID的时候,如果slave的gtid_mode(OFF)不能接受Normal_GTID,那么就会报错2)当master产生ANONYMOUS_GTID的时候,如果slave的gtid_mode(ON)不能接受ANONYMOUS_GTID,那么就会报错3)设置auto_position的条件: 当master的gtid_mode=ON时,slave可以为OFF_PERMISSIVE,ON_PERMISSIVE,ON。 除此之外,都不能设置auto_position = on ============================================下面开始说下如何online 升级为GTID模式? step 1: 每台server执行检查错误日志,直到没有错误出现,才能进行下一步mysql> SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = WARN; step 2: 每台server执行mysql> SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = ON; step 3: 每台server执行不用关心一组复制集群的server的执行顺序,只需要保证每个Server都执行了,才能进行下一步mysql> SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE; step 4: 每台server执行不用关心一组复制集群的server的执行顺序,只需要保证每个Server都执行了,才能进行下一步mysql> SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE; step 5: 在每台server上执行,如果ONGOING_ANONYMOUS_TRANSACTION_COUNT=0就可以不需要一直为0,只要出现过0一次,就okmysql> SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT'; step 6: 确保所有anonymous事务传递到slave上了#master上执行mysql> SHOW MASTER STATUS; #每个slave上执行mysql> SELECT MASTER_POS_WAIT(file, position); 或者,等一段时间,只要不是大的延迟,一般都没问题 step 7: 每台Server上执行mysql> SET @@GLOBAL.GTID_MODE = ON; step 8: 在每台server上将my.cnf中添加好gtid配置gtid_mode=onenforce-gtid-consistency=1log_bin=mysql-binlog-slave-updates=1 step 9: 在从机上通过change master语句进行复制mysql> STOP SLAVE;mysql> CHANGE MASTER TO MASTER_AUTO_POSITION = 1;mysql> START SLAVE;来源:51CTO
  • [技术干货] MySQL调优之慢查询日志应用
     慢查询日志是用于记录SQL执行时间超过某个临界值的SQL日志文件,可用于快速定位慢查询,为我们的SQL优化做参考。  具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。long_query_time的默认值为10,意思是运行10秒以上的SQL语句。  查看是否开启 show variables like '%slow_query_log%'# 本文这里结果如下slow_query_log ONslow_query_log_file DESKTOP-KIHKQLG-slow.log​​slow_query_log_file​​​指的是慢查询日志文件。如果slow_query_log 状态值为OFF,可以使用​​set GLOBAL slow_query_log = on​​来开启,如果想永久生效,那么在MySQL的配置文件中进行配置。[mysqld]slow_query_log=1slow_query_log_file=/var/data/mysql-slow.log#如果不指定日志文件,那么系统会默认一个hostnam-slow.log 查看时间阈值  默认值是10秒,可以根据需求自行调整。 show variables like 'long_query_time';# 临时设置为1 秒,重启失效set GLOBAL long_query_time= 1查询当前慢查询SQL条数show global status like '%Slow_queries%' 慢查询日志格式  需要注意的是,慢查询日志文件里面不止有Query哦,只要执行时间大于我们设置的阈值都会进入。 如下所示是一个慢查询实例,其load了21W条数据。 # Time: 2022-09-14T05:43:57.174825Z# User@Host: root[root] @ localhost [127.0.0.1] Id: 2497# Query_time: 1.697595 Lock_time: 0.000226 Rows_sent: 210001 Rows_examined: 210001SET timestamp=1663134237;/* ApplicationName=DBeaver 7.3.0 - SQLEditor */ select * from tb_sys_user tsu limit 210001; 日志分析工具mysqldumpslow  mysql提供了日志分析工具mysqldumpslow来帮助我们快速定位问题。 [root@VM-24-14-centos ~]# mysqldumpslow --helpUsage: mysqldumpslow [ OPTS... ] [ LOGS... ]Parse and summarize the MySQL slow query log. Options are --verbose verbose --debug debug --help write this text to standard output -v verbose -d debug -s ORDER what to sort by (al, at, ar, c, l, r, t), 'at' is default al: average lock time ar: average rows sent at: average query time c: count l: lock time r: rows sent t: query time -r reverse the sort order (largest last instead of first) -t NUM just show the top n queries -a don't abstract all numbers to N and strings to 'S' -n NUM abstract numbers with at least n digits within names -g PATTERN grep: only consider stmts that include this string -h HOSTNAME hostname of db server for *-slow.log filename (can be wildcard), default is '*', i.e. match all -i NAME name of server instance (if using mysql.server startup script) -l don't subtract lock time from total time得到返回记录集最多的10个SQLmysqldumpslow -s r -t 10 /var/data/mysql-slow.log得到访问次数最多的10个SQLmysqldumpslow -s c -t 10 /var/data/mysql-slow.log得到按照时间排序的前10条SQL中包含左连接的语句mysqldumpslow -s t -t 10 -g "left join" /var/data/mysql-slow.log 慢查询日志场景应用  慢查询的优化首先要搞明白慢的原因是什么, 是查询条件没有命中索引?是 load了不需要的数据列?还是数据量太大?所以优化也是针对这三个方向来的。  首先分析语句,看看是否load了额外的数据​​,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。  ​​分析语句的执行计划,然后获得其使用索引的情况​​,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。  ​​如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大​​,如果是的话可以进行横向或者纵向的分表。 全局查询日志 其同样可以帮助我们定位SQL问题,通常不建议在生产环境开启。可以在配置文件my.cnf下进行启用:# 开启general_log=1#记录日志文件的路径general_log_file=/var/data/mysql_general_log#输出格式log_output=FILE或者临时开启:set global general_log=1;set global log_output='TABLE'此时SQL语句将会记录到MySQL库的​​mysql.general_log​​表中。来源:51CTO
  • [技术干货] 事务基础知识
     一、数据库事务概述 1.1 存储引擎支持情况  SHOW ENGINES命令来查看当前MySQL支持的存储引擎都有哪些,以及这些存储引擎是否支持事务。  SHOW ENGINES命令来查看当前MySQL支持的存储引擎都有哪些,以及这些存储引擎是否支持事务。 1.2 基本概念 事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态。 事务处理的原则:保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态。 1.3 事务的ACID特性 原子性(atomicity):原子性是指事务是一个不可分割的工作单位,要么全部提交,要么全部失败回滚。 一致性(consistency):一致性是指事务执行前后,数据从一个合法性状态变换到另外一个合法性状态。这种状态是语义上的而不是语法上的,跟具体的业务有关。 隔离型(isolation):事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。 持久性(durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。 1.4 事务的状态 我们现在知道事务是一个抽象的概念,它其实对应着一个或多个数据库操作,MySQL根据这些操作所执行的不同阶段把事务大致划分成几个状态:  活动的(active):事务对应的数据库操作正在执行过程中时,我们就说该事务处在活动的状态。 部分提交的(partially committed):当事务中的最后一个操作执行完成,但由于操作都在内存中执行,所造成的影响并没有刷新到磁盘时,我们就说该事务处在部分提交的状态。 失败的(failed):当事务处在活动的或者部分提交的状态时,可能遇到了某些错误(数据库自身的错误、操作系统错误或者直接断电等)而无法继续执行,或者人为的停止当前事务的执行,我们就说该事务处在失败的状态。 中止的(aborted):如果事务执行了一部分而变为失败的状态,那么就需要把已经修改的事务中的操作还原到事务执,行前的状态。换句话说,就是要撤销失败事务对当前数据库造成的影响。我们把这个撤销的过程称之为回滚。当回滚操作执行完毕时,也就是数据库恢复到了执行事务之前的状态,我们就说该事务处在了中止的状态。 提交的(committed):当一个处在部分提交的状态的事务将修改过的数据都同步到磁盘上之后,我们就可以说该事务处在了提交的状态。 状态转换图如下所示:  二、事务隔离级别 2.1 数据并发问题 脏写( Dirty Write ): 对于两个事务 Session A、Session B,如果事务Session A修改了另一个未提交事务Session B修改过的数 据,那就意味着发生了脏写。 脏读( Dirty Read ) :对于两个事务 Session A、Session B,Session A 读取了已经被 Session B更新但还没有被提交的字段。 之后若 Session B 回滚 ,Session A 读取 的内容就是临时且无效的。 不可重复读( Non-Repeatable Read ) :对于两个事务Session A、Session B,Session A读取了一个字段,然后 Session B更新了该字段。 之后 Session A再次读取同一个字段,值就不同了。那就意味着发生了不可重复读。  幻读( Phantom ) 对于两个事务Session A、Session B, Session A 从一个表中读取了一个字段, 然后 Session B 在该表中插入了一些新的行。 之后, 如果 Session A 再次读取同一个表, 就会多出几行。那就意味着发生了幻读。2.2 SQL中的四种隔离级别 READ UNCOMMITTED:读未提交,在该隔离级别,所有事务都可以看到其他未提交事务的执行结 果。不能避免脏读、不可重复读、幻读。 READ COMMITTED :读已提交,它满足了隔离的简单定义:一个事务只能看见已经提交事务所做 的改变。这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。可以避免脏读,但不可 重复读、幻读问题仍然存在。 REPEATABLE READ :可重复读,事务A在读到一条数据之后,此时事务B对该数据进行了修改并提 交,那么事务A再读该数据,读到的还是原来的内容。可以避免脏读、不可重复读,但幻读问题仍 然存在。这是MySQL的默认隔离级别。 SERIALIZABLE :可串行化,确保事务可以从一个表中读取相同的行。在这个事务持续期间,禁止 其他事务对该表执行插入、更新和删除操作。所有的并发问题都可以避免,但性能十分低下。能避 免脏读、不可重复读和幻读。  如下表所示:隔离级别脏读不可重复读幻读加锁读READ UNCOMMITED√√√×READ COMMITTED×√√×REPEATABLE READ××√×SERIALIZABLE××××不同的隔离级别有不同的现象,并有不同的锁和并发机制,隔离级别越高,数据库的并发性能就越差,4 种事务隔离级别与并发性能的关系如下:  2.3 查询隔离级别 mysql> show variables like 'transaction_isolation';+-----------------------+-----------------+| Variable_name | Value |+-----------------------+-----------------+| transaction_isolation | REPEATABLE-READ |+-----------------------+-----------------+1 row in set (0.00 sec)mysql> SELECT @@transaction_isolation;+-------------------------+| @@transaction_isolation |+-------------------------+| REPEATABLE-READ |+-------------------------+1 row in set (0.00 sec)2.4 如何设置事务的隔离级别 通过下面的语句修改事务的隔离级别: SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL 隔离级别;#其中,隔离级别格式:> READ UNCOMMITTED> READ COMMITTED> REPEATABLE READ> SERIALIZABLE或者:SET [GLOBAL|SESSION] TRANSACTION_ISOLATION = '隔离级别'#其中,隔离级别格式:> READ-UNCOMMITTED> READ-COMMITTED> REPEATABLE-READ> SERIALIZABLE三、使用事务操作 专业术语: 事务(transaction):指一组SQL语句; 回退(rollback):指撤销指定的SQL语句的过程; 提交(commit):指将未存储的SQL语句写入数据库表; 保留点(savepoint):指事务处理中设置的临时占位符(place-holder),你可以对它发布回退(与回退整个事务处理不同) 3.1 开启事务 mysql> start transaction;Query OK, 0 rows affected (0.00 sec)或则: mysql> begin;Query OK, 0 rows affected (0.00 sec)3.2 使用ROLLBACK mysql> select * from student;+-----------+------+-------+| studentno | name | class |+-----------+------+-------+| 1 | tom | 1班 || 2 | jack | 2班 |+-----------+------+-------+2 rows in set (0.00 sec)mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> delete from student;Query OK, 2 rows affected (0.00 sec)mysql> select * from student;Empty set (0.00 sec)mysql> rollback;Query OK, 0 rows affected (0.01 sec)mysql> select * from student;+-----------+------+-------+| studentno | name | class |+-----------+------+-------+| 1 | tom | 1班 || 2 | jack | 2班 |+-----------+------+-------+2 rows in set (0.00 sec) mysql>3.3 使用COMMIT SESSION A: 插入数据未提交  mysql> select * from student;+-----------+------+-------+| studentno | name | class |+-----------+------+-------+| 1 | tom | 1班 || 2 | jack | 2班 |+-----------+------+-------+2 rows in set (0.00 sec)mysql> mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> insert into student(studentno,name,class) values(3,'lily','1班');Query OK, 1 row affected (0.00 sec)mysql> select * from student;+-----------+------+-------+| studentno | name | class |+-----------+------+-------+| 1 | tom | 1班 || 2 | jack | 2班 || 3 | lily | 1班 |+-----------+------+-------+3 rows in set (0.00 sec)mysql> SESSION B: 查询数据 mysql> select * from student;+-----------+------+-------+| studentno | name | class |+-----------+------+-------+| 1 | tom | 1班 || 2 | jack | 2班 |+-----------+------+-------+2 rows in set (0.00 sec)mysql> SESSION A: 提交数据 mysql> commit;Query OK, 0 rows affected (0.01 sec)SESSION B: 查询数据 mysql> select * from student;+-----------+------+-------+| studentno | name | class |+-----------+------+-------+| 1 | tom | 1班 || 2 | jack | 2班 || 3 | lily | 1班 |+-----------+------+-------+3 rows in set (0.00 sec)mysql> 3.4 使用SAVEPOINT mysql> select * from student;+-----------+------+-------+| studentno | name | class |+-----------+------+-------+| 1 | tom | 1班 || 2 | jack | 1班 || 3 | lily | 1班 |+-----------+------+-------+3 rows in set (0.00 sec)mysql> start transaction;Query OK, 0 rows affected (0.01 sec)mysql> update student set class = '2.班' where studentno = 3;Query OK, 1 row affected (0.00 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql> select * from student;+-----------+------+-------+| studentno | name | class |+-----------+------+-------+| 1 | tom | 1班 || 2 | jack | 1班 || 3 | lily | 2班 |+-----------+------+-------+3 rows in set (0.00 sec)mysql> savepoint p1;Query OK, 0 rows affected (0.00 sec)mysql> delete from student;Query OK, 3 rows affected (0.00 sec)mysql> select * from student;Empty set (0.01 sec)mysql> rollback to p1;Query OK, 0 rows affected (0.00 sec)mysql> select * from student;+-----------+------+-------+| studentno | name | class |+-----------+------+-------+| 1 | tom | 1班 || 2 | jack | 1班 || 3 | lily | 2班 |+-----------+------+-------+3 rows in set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.01 sec)mysql> select * from student;+-----------+------+-------+| studentno | name | class |+-----------+------+-------+| 1 | tom | 1班 || 2 | jack | 1班 || 3 | lily | 2班 |+-----------+------+-------+3 rows in set (0.00 sec)mysql> 来源:51CTO
  • [技术干货] 如何干涉MySQL优化器使用hash join?
    数据库的优化器相当于人类的大脑,大部分时候都能做出正确的决策,制定正确的执行计划,走出一条高效的路,但是它毕竟是基于某些固定的规则、算法来做的判断,有时候并没有我们人脑思维灵活,当我们确定优化器选择执行计划错误时该怎么办呢,语句上加hint,提示它选择哪条路是一种常见的优化方法。前言数据库的优化器相当于人类的大脑,大部分时候都能做出正确的决策,制定正确的执行计划,走出一条高效的路,但是它毕竟是基于某些固定的规则、算法来做的判断,有时候并没有我们人脑思维灵活,当我们确定优化器选择执行计划错误时该怎么办呢,语句上加hint,提示它选择哪条路是一种常见的优化方法。我们知道Oracle提供了比较灵活的hint提示来指示优化器在多表连接时选择哪种表连接方式,比如use_nl,no_use_nl控制是否使用Nest Loop Join,use_hash,no_use_hash控制是否使用hash join。但是MySQL长期以来只有一种表连接方式,那就是Nest Loop Join,直到MySQL8.0.18版本才出现了hash join, 所以MySQL在控制表连接方式上没有提供那么多丰富的hint给我们使用,hash_join与no_hash_join的hint只是惊鸿一瞥,只在8.0.18版本存在,8.0.19及后面的版本又将这个hint给废弃了,那如果我们想让两个表做hash join该怎么办呢?实验我们来以MySQL8.0.25的单机环境做一个实验。建两个表,分别插入10000行数据,使用主键做这两个表的关联查询。create table t1(id int primary key,c1 int,c2 int);create table t2(id int primary key,c1 int,c2 int);delimiter //CREATE PROCEDURE p_test()BEGINdeclare i int;set i=1;while i<10001 doinsert into t1 values(i,i,i);insert into t2 values(i,i,i);SET i = i + 1;end while;END;//delimiter ;查询一下两表使用主键字段关联查询时实际的执行计划,如下图所示:查询一下两表使用非索引字段关联查询时实际的执行计划,如下图所示:从执行计划可以看出,被驱动表的关联字段上有索引,优化器在选择表连接方式时会倾向于选择Nest Loop Join,当没有可用索引时倾向于选择hash join。基于这一点那我们可以使用no_index提示来禁止语句使用关联字段的索引。从上面的执行计划可以看出使用no_index提示后,优化器选择了使用hash join。当索引的选择性不好时,优化器选择使用索引做Nest Loop Join是效率是很低的。我们将实验的两个表中c1列的数据做一下更改,使其选择性变差,并在c1列上建普通索引。update t1 set c1=1 where id<5000;update t2 set c1=1 where id<5000;create index idx_t1 on t1(c1);create index idx_t2 on t2(c1);当我们执行sql :select t1.*,t2.* from t1 join t2 on t1.c1=t2.c1;这个查询结果会返回大量数据,被驱动表的关联字段c1列的索引选择性差,此时选择hash join是更明智的选择,但是优化器会选择走Nest Loop Join。我们可以通过实验验证一下hash join 与 Nest Loop Join的性能差异。可以看出使用hash join的耗时是使用Nest Loop Join的1/6,但是优化器根据成本估算时,使用Nest Loop Join的成本要比使用hash join的成本低很多,所以会去选择Nest Loop Join,这个时候就需要加上hint 提示禁止使用关联字段的索引,被驱动表上每次都全表扫描的代价是很高的,这样优化器估算后就会选择走hash join。MySQL官方文档里提到用BNL,NO_BNL的hint提示来影响hash join的优化,但是经过实验证明,在表连接关联字段上没有可用索引时,优化器估算成本后不会对被驱动表使用BNL全表扫描的方式做嵌套循环连接,而是会选择使用hash join,那这样NO_BNL在这个场景下就没有用武之地了。那么既然不用这个索引,把这个索引去掉不就可以了吗?为什么非要使用no_index的hint提示呢,我们要知道业务使用的场景何其多,此处不用,别处使用了这个索引效率可能会有大的提升啊,这个时候就凸显了hint的优势,只需要控制此语句的使用就好了。总结Nest Loop Join有其优势,它是response最快的连接方式,适用于返回数据量小的场景。当两个大表连接,返回大量数据,且关联字段的索引比较低效时,使用hash join就会比较高效,我们可以使用no_index的hint提示禁用关联字段的低效索引,促使优化器选择hash join。来源: GreatSQL社区
  • [数据库] MySQL细粒度锁优化特性咨询?
    现网为MySQL 8.0.20,我的myql是已经安装编译好了的,想通过安装MySQL细粒度锁优化特性和MySQL无锁优化特性两个补丁包对mysql进行优化。查看操作手册存在如下问题?麻烦大神帮忙解答下我的myql是已经安装编译好了的,是否只需要下载对应的补丁包,通过步骤3和步骤4合入补丁就行了?还是需要按照步骤5对mysql重新编译安装?如果需要对现有mysql重新安装编译,那是否意味着需要对mysql重新初始化等操作???
  • [技术干货] 8月数据库排行榜:Oracle 大跌,MySQL上涨
    Oracle 较上月减少了 19.50 分,是本月分数下降最多的数据库,并且连续两个月出现了下滑。分数上涨较多的则是 MySQL 和 MongoDB,两者分别增加了 7.98 和 4.68 分。DB-Engines 数据库流行度排行榜发布了 8 月份的更新。可以看到,Oracle 较上月减少了 19.50 分,是本月分数下降最多的数据库,并且连续两个月出现了下滑。分数上涨较多的则是 MySQL 和 MongoDB,两者分别增加了 7.98 和 4.68 分。不过和去年同期相比,三巨头(Oracle、MySQL 和 SQL Server)和 MongoDB 的分数均下降了不少。与之形成对比的 PostgreSQL 则保持着稳定的上升趋势,其每月流行度分数跟去年同期相比都有不少的上涨。下表是 TOP 10 数据库的最新分数和变化情况。继续看看主流数据库的分数趋势变化:最后看看各类型数据库的排名情况。关系数据库前 10 名Key-Value 数据库前 10 名文档数据库前 10 名时序数据库前 10 名图数据库前 10 名DB-Engines 根据流行度对数据库管理系统进行排名,排名每月更新一次。排名的数据依据 5 个不同的指标:Google 以及 Bing 搜索引擎的关键字搜索数量Google Trends 的搜索数量Indeed 网站中的职位搜索量LinkedIn 中提到关键字的个人资料数Stackoverflow 上相关的问题和关注者数量这份榜单分析旨在为数据库相关从业人员提供一个技术方向的参考,其中涉及到的排名情况并非基于产品的技术先进程度或市场占有率等因素。无论排名先后,选择适合与企业业务需求相比配的技术才是最重要的。来源:OSCHINA
  • [问题求助] MySQL 返回 #1054 - Unknown column &apos;pics&apos; in &apos;field list&apos;
    【操作步骤&问题现象】在本地pbootcms网站测试中,我想要将Sqlite数据库转mysql数据库。 mysql版本5.7然后报错:  #1054 - Unknown column 'picstitle' in 'field list'【截图信息】
  • [技术干货] mysql5.7 性能优化配置 innodb_buffer_pool_size[转载]
    一、缓冲池​​​​​14.5.1 Buffer Pool缓冲池是主内存中的一个区域,InnoDB在访问表和索引数据时将其缓存。缓冲池允许直接从内存访问经常使用的数据,从而加快处理速度。在专用服务器上,高达80%的物理内存通常分配给缓冲池。为了提高大容量读取操作的效率,缓冲池被划分为可能容纳多行的页面。为了提高缓存管理的效率,缓冲池被实现为页面的链接列表;很少使用的数据会使用最不常用(LRU)算法的变体从缓存中过时。了解如何利用缓冲池将频繁访问的数据保存在内存中是MySQL调优的一个重要方面。二、innodb_buffer_pool_size14.8.3.1 Configuring InnoDB Buffer Pool Sizeinnodb_buffer_pool_size=innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances. innodb_buffer_pool_size默认是128M,缓冲池的大小(字节),InnoDB缓存表和索引数据的内存区域。默认值为134217728字节(128MB)。最大值取决于CPU架构;32位系统的最大值为4294967295(2**32-1),64位系统的最大值为18446744073709551615(2**64-1)。在32位系统上,CPU体系结构和操作系统的实际最大大小可能低于规定的最大大小。当缓冲池的大小大于1GB时,将innodb_buffer_pool_instances设置为大于1的值可以提高繁忙服务器上的可伸缩性。更大的缓冲池需要更少的磁盘I/O来多次访问相同的表数据。在专用数据库服务器上,可以将缓冲池大小设置为机器物理内存大小的80%。在配置缓冲池大小时,请注意以下潜在问题,并准备在必要时缩小缓冲池的大小。对物理内存的竞争可能会导致操作系统中的分页。InnoDB为缓冲区和控制结构保留额外的内存,因此总分配空间比指定的缓冲池大小大约大10%。缓冲池的地址空间必须是连续的,这在具有在特定地址加载DLL的Windows系统上可能是一个问题。初始化缓冲池的时间大致与其大小成正比。在具有大型缓冲池的实例上,初始化时间可能很长。要缩短初始化周期,可以在服务器关闭时保存缓冲池状态,并在服务器启动时恢复。参见第14.8.3.6节“保存和恢复缓冲池状态”。当增加或减少缓冲池大小时,该操作将分块执行。区块大小由innodb_buffer_pool_chunk_size变量定义,该变量的默认值为128 MB。缓冲池大小必须始终等于或是innodb_buffer_pool_chunk_size*innodb_buffer_pool_instances的倍数。如果将缓冲池大小更改为不等于innodb_buffer_pool_chunk_size*innodb_buffer_pool_instances的值或其倍数,缓冲池大小将自动调整为等于或其倍数的值。innodb_buffer_pool_size可以动态设置,这允许您在不重新启动服务器的情况下调整缓冲池的大小。Innodb_buffer_pool_resize_status变量报告在线缓冲池大小调整操作的状态。有关更多信息,请参阅第14.8.3.1节“配置InnoDB缓冲池大小”。innodb_buffer_pool_chunk_size 默认是128Minnodb_buffer_pool_instances默认是8(如果innodb_buffer_pool_size < 1GB,则是1)14.8.3.2 Configuring Multiple Buffer Pool Instances2.1查看现有配置mysql> show variables like 'innodb_buffer_pool%';+-------------------------------------+----------------+| Variable_name                       | Value          |+-------------------------------------+----------------+| innodb_buffer_pool_chunk_size       | 134217728      || innodb_buffer_pool_dump_at_shutdown | ON             || innodb_buffer_pool_dump_now         | OFF            || innodb_buffer_pool_dump_pct         | 25             || innodb_buffer_pool_filename         | ib_buffer_pool || innodb_buffer_pool_instances        | 1              || innodb_buffer_pool_load_abort       | OFF            || innodb_buffer_pool_load_at_startup  | ON             || innodb_buffer_pool_load_now         | OFF            || innodb_buffer_pool_size             | 134217728      |+-------------------------------------+----------------+2.2简单优化把innodb_buffer_pool_size设置为1G。个人建议innodb_buffer_pool_size设置为系统内存的50%。最好设置为:innodb_buffer_pool_size=innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances.否则,innodb_buffer_pool_size自动调整可能是innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances的两倍。my.cnf# innodb缓冲池大小innodb_buffer_pool_size=1G # innodb缓冲池块大小innodb_buffer_pool_chunk_size=128M # innodb缓冲池实例数innodb_buffer_pool_instances=8重启数据库调整后:mysql> show variables like 'innodb_buffer_pool%';+-------------------------------------+----------------+| Variable_name                       | Value          |+-------------------------------------+----------------+| innodb_buffer_pool_chunk_size       | 134217728      || innodb_buffer_pool_dump_at_shutdown | ON             || innodb_buffer_pool_dump_now         | OFF            || innodb_buffer_pool_dump_pct         | 25             || innodb_buffer_pool_filename         | ib_buffer_pool || innodb_buffer_pool_instances        | 8              || innodb_buffer_pool_load_abort       | OFF            || innodb_buffer_pool_load_at_startup  | ON             || innodb_buffer_pool_load_now         | OFF            || innodb_buffer_pool_size             | 1073741824     |+-------------------------------------+----------------+这些参数也支持在线调整,可考虑在业务低峰时调整。Configuring InnoDB Buffer Pool Size Online2.3配置是否合适5.1.3 Server Option, System Variable, and Status Variable Reference2.3.1查询缓存命中率:mysql> show status like 'Innodb_buffer_pool_read%';+---------------------------------------+--------------+| Variable_name                         | Value        |+---------------------------------------+--------------+| Innodb_buffer_pool_read_ahead_rnd     | 0            || Innodb_buffer_pool_read_ahead         | 20294922     || Innodb_buffer_pool_read_ahead_evicted | 1240192      || Innodb_buffer_pool_read_requests      | 299216558100 || Innodb_buffer_pool_reads              | 1167281260   |+---------------------------------------+--------------+Innodb_buffer_pool_read_requests:逻辑读取请求的数量。Innodb_buffer_pool_reads:InnoDB无法从缓冲池满足的逻辑读取数,必须直接从磁盘读取。percent = innodb_buffer_pool_read_requests / (innodb_buffer_pool_reads + innodb_buffer_pool_read_requests) * 100%上述的 percent>=99%,则表示当前的buffer pool满足当前的需求。否则需要考虑增加 innodb_buffer_pool_size的值。2.3.2缓存数据页占比:mysql> show status like 'Innodb_buffer_pool_pages%';+----------------------------------+----------+| Variable_name                    | Value    |+----------------------------------+----------+| Innodb_buffer_pool_pages_data    | 7003     || Innodb_buffer_pool_pages_dirty   | 0        || Innodb_buffer_pool_pages_flushed | 19906085 || Innodb_buffer_pool_pages_free    | 1021     || Innodb_buffer_pool_pages_misc    | 167      || Innodb_buffer_pool_pages_total   | 8191     |+----------------------------------+----------+innodb_buffer_pool_pages_data:InnoDB缓冲池中包含数据的页数。这个数字包括脏页和干净页。(使用压缩表时,报告的Innodb_buffer_pool_pages_数据值可能大于)percent = Innodb_buffer_pool_pages_data / Innodb_buffer_pool_pages_total * 100%上述的 percent>=95% 则表示当前的innodb_buffer_pool_size满足当前的需求。否则可以考虑增加 innodb_buffer_pool_size的值。2.4如何判断MySQL使用内存会不会过高可能还有有一些担心,所有参数设置完毕后MySQL的占用会过高导致内存溢出,那么我们可以算一下他会不会太高。通过下面的SQL语句:SELECT ((@@key_buffer_size+@@innodb_buffer_pool_size+@@innodb_log_buffer_size)/1024/1024)+((@@read_rnd_buffer_size+@@read_buffer_size+@@myisam_sort_buffer_size+@@sort_buffer_size+@@join_buffer_size)/1024/1024*@@max_connections);最终单位为MB若该值不超过系统可用内存,说明还好(理论)2.5其他命令mysql> show status like 'Innodb_buffer_pool%';+---------------------------------------+--------------------------------------------------+| Variable_name                         | Value                                            |+---------------------------------------+--------------------------------------------------+| Innodb_buffer_pool_dump_status        | Dumping of buffer pool not started               || Innodb_buffer_pool_load_status        | Buffer pool(s) load completed at 220313  7:31:02 || Innodb_buffer_pool_resize_status      |                                                  || Innodb_buffer_pool_pages_data         | 6999                                             || Innodb_buffer_pool_bytes_data         | 114671616                                        || Innodb_buffer_pool_pages_dirty        | 0                                                || Innodb_buffer_pool_bytes_dirty        | 0                                                || Innodb_buffer_pool_pages_flushed      | 19905034                                         || Innodb_buffer_pool_pages_free         | 1024                                             || Innodb_buffer_pool_pages_misc         | 168                                              || Innodb_buffer_pool_pages_total        | 8191                                             || Innodb_buffer_pool_read_ahead_rnd     | 0                                                || Innodb_buffer_pool_read_ahead         | 20294410                                         || Innodb_buffer_pool_read_ahead_evicted | 1240164                                          || Innodb_buffer_pool_read_requests      | 299111990637                                     || Innodb_buffer_pool_reads              | 1167212424                                       || Innodb_buffer_pool_wait_free          | 1193110                                          || Innodb_buffer_pool_write_requests     | 156029072                                        |+---------------------------------------+--------------------------------------------------+mysql> show engine innodb status \Gmysql> SHOW GLOBAL STATUS \G 太多了。三、其他待优化:join_buffer_size = 128Msort_buffer_size = 2Mread_rnd_buffer_size = 2Mmysql> show variables like '%buffer_size%';+-------------------------+----------+| Variable_name           | Value    |+-------------------------+----------+| bulk_insert_buffer_size | 8388608  || innodb_log_buffer_size  | 16777216 || innodb_sort_buffer_size | 1048576  || join_buffer_size        | 262144   || key_buffer_size         | 8388608  || myisam_sort_buffer_size | 8388608  || preload_buffer_size     | 32768    || read_buffer_size        | 131072   || read_rnd_buffer_size    | 262144   || sort_buffer_size        | 262144   |+-------------------------+----------+四、参考:Mysql优化之innodb_buffer_pool_size篇MySQL参数 之 innodb_buffer_pool_sizeMySQL中innodb_buffer_pool_size的配置MySQL基准测试innodb_buffer_pool_size对性能影响五、文档:Chapter 8 Optimization8.1 Optimization Overview8.2 Optimizing SQL Statements8.3 Optimization and Indexes8.4 Optimizing Database Structure8.5 Optimizing for InnoDB Tables8.6 Optimizing for MyISAM Tables8.7 Optimizing for MEMORY Tables8.8 Understanding the Query Execution Plan8.9 Controlling the Query Optimizer8.10 Buffering and Caching8.11 Optimizing Locking Operations8.12 Optimizing the MySQL Server        8.12.4.1 How MySQL Uses Memory8.13 Measuring Performance (Benchmarking)8.14 Examining Server Thread (Process) Information8.5 Optimizing for InnoDB Tables8.5.1 Optimizing Storage Layout for InnoDB Tables8.5.2 Optimizing InnoDB Transaction Management8.5.3 Optimizing InnoDB Read-Only Transactions8.5.4 Optimizing InnoDB Redo Logging8.5.5 Bulk Data Loading for InnoDB Tables8.5.6 Optimizing InnoDB Queries8.5.7 Optimizing InnoDB DDL Operations8.5.8 Optimizing InnoDB Disk I/O8.5.9 Optimizing InnoDB Configuration Variables8.5.10 Optimizing InnoDB for Systems with Many Tables14.8.3 InnoDB Buffer Pool Configuration14.8.3.1 Configuring InnoDB Buffer Pool Size14.8.3.2 Configuring Multiple Buffer Pool Instances14.8.3.3 Making the Buffer Pool Scan Resistant14.8.3.4 Configuring InnoDB Buffer Pool Prefetching (Read-Ahead)14.8.3.5 Configuring Buffer Pool Flushing14.8.3.6 Saving and Restoring the Buffer Pool State————————————————版权声明:本文为CSDN博主「躁动的青年」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/haveqing/article/details/124788083
  • [技术干货] 新数据库时代,不要只学 Oracle、MySQL
    目前,中国已经进入“人人都是开发者,家家都是数据公司”的新数据库时代。今日,CSDN 创始人&董事长、极客帮创投创始合伙人蒋涛发表了《新数据库时代》主题演讲分享。他指出,在开源吞噬世界的背景下,数据库也在大力拥抱开源。不同于传统关系型数据库,新型数据库已成为行业风口,急需大量相关人才汇入,青年才俊应当抓住机遇,迎接挑战。以下是蒋涛演讲实录:大家好,我是CSDN创始人蒋涛。我是程序员出身,30年前数据库就是程序员的必备技能,而近几年,数据库又有了很大的发展。作为投资人,我也曾投资过巨杉数据库。CSDN目前是中国知名的技术社区,据最新数据显示,CSDN的用户量已经超过3,600万,公司规模也在不断发展壮大。如今,开发者变得越来越重要,我们围绕着开发者建立了一系列业务支持体系,帮助开发者获得能力与成长。其中,不仅有协助开发的工具开发云(https://dev.csdn.net),还有帮助大家找到更好职业的人才云等。目前,开发者市场越来越好,相信“人人都是开发者,家家都是技术公司”的时代不久后就要到来。在此背景下,中国想要构建自己的核心技术生态,数据库是其中关键。今天我将围绕三个部分分享《新数据库时代》:第一是揭示「我们正在进入的数据大时代」现状;第二是了解「开源正在吞噬数据库」的改变;第三是把握「新型的数据库人才特别抢手」的趋势。1、数据大时代我们正处于大数据时代,几乎每家公司都在对自己的业务进行数字化变革。据统计,全球数据量每年持续增加,去年全球产生的数据总量是79ZB,2025年预计将达到180ZB。由于云技术的发展,越来越多的数据都存储在云端。数据显示,在2016年只有10%的数据储存在云端的数据仓库里,但到了2022年,这个数字已经快速增长到了75%,这说明随着数字经济的发展,每家公司都将成为数据公司,数据库市场也迎来了爆炸性增长。数据库市场历史其实非常悠久,从1964年,世界上第一个数据库系统IDS(Integrated Data Storage,集成数据存储)诞生开始,到今天数据库发展已经快60年。1980年代,数据库开始在中国生根发芽。直到现在,整个全球市场依然保持了20%以上的增长规模。尽管数据库是个古老的技术,但其中又蕴含了很多新的机会。从数据库技术公司融资情况来看,数字非常惊人。过去10年,数据库公司融资总额87亿,其中一半是在过去两年内完成的。2021年,超级独角兽大数据公司Databricks两轮融资总额为26亿美元。如此看来,数据库技术也进入到了一个新时代。2、开源吞噬数据库那么数据库的技术进入到新时代的标志是什么?即“开源吞噬数据库”。开源已经成为所有开发者的必选项,据GitHub统计数据:2016年仅有80万人第一次做出开源代码贡献,而2021年,这个数字已经增长到300万。在数据库领域中,开源的“吞噬”情况也十分明显。dbdb.io(卡内基梅隆大学维护的全球数据库信息库)分析了全球知名的841个数据库系统,其中开源数据库有608个,占比72%,只有200多家是商业数据库。在全球顶尖数据库排行榜中,开源数据库也占到一半。在CSDN制作的2021 数据库全景图(V1.0)中,我们将不同领域的数据库按照开源和闭源两类进行颜色区分,右侧浅绿色的部分是开源数据库,左侧深绿色的部分是闭源数据库。可以很明显地看到开源在快速发展,且有吞噬闭源数据库的趋势。中国数据库在发展核心技术生态的大背景下,也发展得非常的迅猛。dbdb.io(卡内基梅隆大学维护的全球数据库信息库)统计的全球800多家数据库企业中,中国有56家,但实际上中国数据库厂商有200多家。尤其在新型数据库上,中国企业“冒头”较多,例如现在发展势头强劲的TiDB,在GitHub上非常活跃。当然,开发者目前使用较多的还是相对传统的基础关系型数据库MySQL,还有大数据领域Redis、Apache/Hive、MongoDB等相对比较传统的技术,但绝大部分都是开源的。尽管最普遍被使用的依然是关系型数据库,但新型数据库则代表了未来趋势。根据CSDN 2021-2022年数据库开发者大调查显示,在云趋势下,有52%的公司已经部署了云数据库,只有23%的公司尚未计划部署云数据库。新型数据库人才抢手对于目前的就业环境,我认为开发者应当好好学习数据库技术,并且不要局限于仅学习关系型数据库,更要学新型数据库。为什么呢?新型数据库的技术栈跟过去大有不同,关系型数据库只是里面最基础的一环,而数据分析、数据仓库、可视化等很多新型技术栈在涌现。开源中比较热门的新数据库类型包括分布式数据库、时序数据库、图数据库、流式数据库等都在GitHub上排名非常靠前,Star数也非常高。20年前,市面上只有关系型数据库,主要面向事务性的交易。而如今得益于云、微服务、分布式应用、全球规模、实时数据、深度学习等,新的数据库架构应运而生,以解决新的性能需求:快速读取和快速写入的不同系统;专门用于支持实时分析的系统;用于非结构化、半结构化、事务性、关系、图形或时间序列数据的系统;适用于缓存、搜索、基于索引、事件等的数据……据统计,一家企业平均在七个或更多不同的数据库中存储数据。这些新技术带来了新机会,同时也加大了市场对人才的需求。我国数据工程师真正诞生是在十几年前。而现在,随着数据量的激增且更多地存储在云端,越来越多公司变成数据公司、市场对数据公司的需求也在持续增长。基于数据做分析的数据分析工程师也非常重要,他们既要了解数据库的技术,又要懂业务,才能更好地进行数据分析,这样的人才在未来会非常紧俏。据Glassdoor(美国一家做企业点评与职位搜索的职场社区)统计,从2016年到2020年,“数据科学家”在美国最佳工作排行榜中一直位居榜首,被称为21世纪最性感的工作。现在,数据科学家和数据工程师的需求还在持续上升,薪资也是。目前,中国对数据库人才的需求也具有相同趋势,尽管过去在关系型数据库领域处于引领地位的还是Oracle的MySQL数据库。但我相信,中国未来会构建自己的数据库新生态。中国也非常有机会在新技术上进行弯道超车,例如腾讯云数据库TDSQL,以及其他新型数据库。同时,也希望更多CSDN平台上的开发者能够加入新型数据库赛道中来,并欢迎大家去参加能力认证活动。