-
数据库迁移就是把数据从一个系统移动到另一个系统上,迁移过程其实就是在源数据库备份和目标数据库恢复的过程组合。迁移的原因是多种多样的,比如:需要安装新的数据库服务器MySQL 版本更新数据库管理系统的变更(如从 SQL Server 迁移到 MySQL)根据实际操作等情况,可以将数据库迁移操作分成以下 3 种形式。相同版本 MySQL 数据库之间的迁移。不同版本 MySQL 数据库之间的迁移。不同数据库间的迁移。下面将详细介绍数据库迁移的各种方式。1. 相同版本的迁移相同版本的 MySQL 数据库是指主版本号一致的数据库。主版本号一致的数据库迁移最容易实现。由于迁移前后 MySQL 数据库的主版本号相同,所以可以通过复制数据库目录来实现数据库迁移。最安全和最常用的方式是通过使用 mysqldump 命令进行数据库备份,然后使用 mysql 命令将备份文件还原到新的 MySQL 数据库。迁移时的备份和还原操作可以同时执行。假设从一个名为 hostname1 的机器中备份出所有数据库,然后将这些数据库迁移到名为 hostname2 的机器上,具体语法形式如下:mysqldump -h hostname1 -u root -password=password1 -all-databases|mysql -h hostname2 -u root -password=password2其中:符号“|”用来实现将命令 mysqldump 备份的文件送给 mysql 命令;password1 为 hostname1 主机上 root 用户的密码;password2 为 hostname2 主机上 root 用户的密码;-all-databases 表示迁移全部的数据库,可省略。通过上述语句就可以直接迁移。2. 不用版本的迁移不同版本的 MySQL 数据库之间的数据迁移通常是 MySQL 升级的原因。例如,服务器使用 4.0 版本的 MySQL 数据库,现在要升级为 5.7 版本的。这样就需要不同版本的 MySQL 数据库之间进行数据迁移。不同版本下的数据库迁移,分为 2 种方式:低版本数据库向高版本数据库进行迁移高版本数据库向低版本数据库进行迁移低版本数据库向高版本数据库进行迁移时,由于高版本会兼容低版本,所以该种方式也是最容易实现的操作。对于存储类型为 MyISAM 的表,最安全和最常用的操作是直接复制数据文件。对于存储类型为 InnoDB 的表,最安全和最常用的操作是执行 mysqldump 命令进行备份和执行 mysql 命令还原恢复数据。但是高版本数据库向低版本数据库进行迁移时,因为高版本数据库可能有一些新的特性,这些特性是低版本数据库所不具有的,所以数据库迁移时要特别小心,最好使用 mysqldump 命令来进行备份,避免迁移时造成数据丢失。3. 不同数据库的迁移不同数据库之间的迁移是指从其它类型的数据库迁移到 MySQL 数据库,或者从 MySQL 数据库迁移到其他类型的数据库。例如,某个网站原来使用 Oracle 数据库,因为运营成本太高等诸多原因,希望改用 MySQL 数据库。或者,某个管理系统原来使用 MySQL 数据库,因为某种特殊性能的要求,希望改用 Oracle 数据库。这样的不同数据库之间的迁移也经常会发生。但是这种迁移没有普通适用的解决办法。其它数据库也有类似 mysqldump 这样的备份工具,可以将数据库中的文件备份成 sql 文件或普通文本。但是,不同的数据库厂商并没有完全按照 SQL 标准来设计数据库,这就造成了不同数据库使用的 SQL 语句的差异。例如,微软的 SQL Server 软件使用的是 T-SQL 语言。T-SQL 中包含了非标准的 SQL 语句。这就造成了 SQL Server 和 MySQL 的 SQL 语句不能兼容。除了 SQL 语句存在不兼容的情况外,不同的数据库之间的数据类型也有差异。例如,MySQL 不支持 SQL Server 中的 ntext、 Image 等数据类型。同样,SQL Server 也不支持 MySQL 中的 ENUM 和 SET 等数据类型。数据类型的差异也造成了迁移的困难。从某种意义上说,这种差异是商业数据库公司故意造成的壁垒,这种行为是阻碍数据库市场健康发展的。但是不同数据库服务器间的迁移并不是完全不可能。在 Windows 操作系统下,如果要实现从 MySQL 数据库服务器向 SQL SERVER 数据库服务器迁移,可以通过 MyODBC 来实现;如果要实现从 MySQL 数据库服务器向 ORACLE 数据库服务器迁移,可以先通过执行 mysqldump 命令导出 sql 文件,然后手动修改 sql 文件中的 CREATE 语句。
-
MySQL 权限表在数据库启动时载入内存,用户通过身份认证后,系统会在内存中进行相应权限的存取。当 MySQL 允许一个用户执行各种操作时,它将首先核实该用户向 MySQL 服务器发送的连接请求,然后确认用户的操作请求是否被允许。当用户进行连接时,MySQL 实现权限控制主要有以下两个阶段:1)连接核实阶段登录 MySQL 服务器时,客户端连接请求中会提供用户名称、主机地址和密码,MySQL 服务器会使用 user 表中的 Host、User 和 authentication_string (MySQL 5.7 版本之前是 Password)字段执行身份检查。只有客户端请求的主机名和用户名在 user 表中有匹配的记录,并且密码正确时,MySQL 服务器才会通过身份认证,接受连接,否则拒绝连接。MySQL 通过 IP 地址和用户名联合进行身份认证。例如 MySQL 安装后默认创建的用户 root@localhost,表示用户 root 只能从本地(localhost)进行连接时才能通过认证。此用户从其它任何主机对数据库进行连接时都将被拒绝。也就是说,用户名相同,IP 地址不同,MySQL 则将其视为不同的用户。服务器接受连接后进入请求核实阶段等待用户请求。如果连接核实没有通过,服务器则完全拒绝访问。2)请求核实阶段建立连接后,服务器进入请求核实阶段,对在此连接上的每个请求,服务器都会检查用户是否有足够的权限来执行它。这正是授权表中的权限列发挥作用的地方。权限按照以下权限表的顺序得到数据库权限:user→db→tables_priv→columns_priv→procs_priv。在这几个权限表中,权限范围依次递减,全局权限覆盖局部权限。请求核实的过程如下所示:1)用户向 MySQL 发出操作请求。2)MySQL 首先检查 user 表,匹配 User、Host 字段值,查看请求的全局权限在 user 表中是否被授权。授权则允许操作执行,如果指定的权限在 user 表中没有被授权。MySQL 将检查 db 表。3)db 表是下一安全层级,其中的权限限定于数据库层级,在该层级的 SELECT 权限允许用户查看指定数据库的所有表中的数据。MySQL 检查 db 权限表中的权限信息,匹配 User、Host 字段值,查看请求的数据库级别的权限在 db 表中是否被授权。授权则允许操作执行,否则 MySQL 继续向下查找。4)MySQL 检查 tables_priv 权限表中的权限信息,匹配 User、Host 字段值,查看请求的数据表级别的权限在 tables_priv 表中是否被授权。授权则允许操作执行,否则 MySQL 继续向下查找。5)MySQL 检查 columns_priv 权限表中的权限信息,匹配 User、Host 字段值,查看请求的列级别的权限在 columns_priv 表中是否被授权。授权则允许操作执行,否则 MySQL 继续向下查找。6)如果所有权限表都检查完毕,还是没有找到允许的权限操作,那么 MySQL 将返回错误信息,即用户请求的操作不能执行,操作失败。提示:上面提到 MySQL 通过向下层级的顺序检查权限表,但并不意味着所有的权限都要执行该过程。例如,一个用户登录到 MySQL 服务器之后只执行对 MySQL 的管理操作,此时只涉及管理权限,因此 MySQL 只检查 user 表。
-
为了保证数据并发访问时的一致性和有效性,任何一个数据库都存在锁机制。锁机制的优劣直接影响到数据库的并发处理能力和系统性能,所以锁机制也就成为了各种数据库的核心技术之一。锁机制是为了解决数据库的并发控制问题而产生的。如在同一时刻,客户端对同一个表做更新或查询操作,为了保证数据的一致性,必须对并发操作进行控制。同时,锁机制也为实现 MySQL 的各个隔离级别提供了保证。可以将锁机制理解为使各种资源在被并发访问时变得有序所设计的一种规则。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库显得尤其重要,也更加复杂。本节我们先简单介绍一下锁机制及常见的锁类型。按锁级别分类,可分为共享锁、排他锁和意向锁。也可以按锁粒度分类,可分为行级锁、表级锁和页级锁。下面我们先介绍共享锁、排他锁和意向锁。1. 共享锁共享锁的代号是 S,是 Share 的缩写,也可称为读锁。是一种可以查看但无法修改和删除的数据锁。共享锁的锁粒度是行或者元组(多个行)。一个事务获取了共享锁之后,可以对锁定范围内的数据执行读操作。会阻止其它事务获得相同数据集的排他锁。2. 排他锁排他锁的代号是 X,是 eXclusive 的缩写,也可称为写锁,是基本的锁类型。排他锁的粒度与共享锁相同,也是行或者元组。一个事务获取了排他锁之后,可以对锁定范围内的数据执行写操作。允许获得排他锁的事务更新数据,阻止其它事务取得相同数据集的共享锁和排他锁。如有两个事务 A 和 B,如果事务 A 获取了一个元组的共享锁,事务 B 还可以立即获取这个元组的共享锁,但不能立即获取这个元组的排他锁,必须等到事务 A 释放共享锁之后才可以。如果事务 A 获取了一个元组的排他锁,事务 B 不能立即获取这个元组的共享锁,也不能立即获取这个元组的排他锁,必须等到 A 释放排他锁之后才可以。3. 意向锁为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB 还有两种内部使用的意向锁。意向锁是一种表锁,锁定的粒度是整张表,分为意向共享锁(IS)和意向排他锁(IX)两类。意向共享锁表示一个事务有意对数据上共享锁或者排他锁。“有意”表示事务想执行操作但还没有真正执行。锁和锁之间的关系,要么是相容的,要么是互斥的。锁 a 和锁 b 相容是指:操作同样一组数据时,如果事务 t1 获取了锁 a,另一个事务 t2 还可以获取锁 b;锁 a 和锁 b 互斥是指:操作同样一组数据时,如果事务 t1 获取了锁 a,另一个事务 t2 在 t1 释放锁 a 之前无法释放锁 b。锁模式的兼容情况其**享锁、排他锁、意向共享锁、意向排他锁相互之间的兼容/互斥关系如下表所示,其中 Y 表示相容,N 表示互斥。参数XSIXISX(排他锁)NNNNS(共享锁)NYNYIX(意向排他锁)NNYYIS(意向共享锁)NYYY如果一个事务请求的锁模式与当前的锁兼容,InnoDB 就将请求的锁授予该事务;反之,如果两者不兼容,该事务就要等待锁释放。为了尽可能提高数据库的并发量,需每次锁定的数据范围越小越好,越小的锁其耗费的系统资源越多,系统性能下降。为在高并发响应和系统性能两方面进行平衡,这样就产生了“锁粒度”的概念。
-
MySQL 按锁的粒度可以细分为行级锁、页级锁和表级锁。我们可以将锁粒度理解成锁范围。1)表级锁(table lock)表级锁为表级别的锁定,会锁定整张表,可以很好的避免死锁,是 MySQL 中最大颗粒度的锁定机制。一个用户在对表进行写操作(插入、删除、更新等)时,需要先获得写锁,这会阻塞其它用户对该表的所有读写操作。没有写锁时,其它读取的用户才能获得读锁,读锁之间是不相互阻塞的。表级锁最大的特点就是实现逻辑非常简单,带来的系统负面影响最小。所以获取锁和释放锁的速度很快。当然,锁定颗粒度大带来最大的负面影响就是出现锁定资源争用的概率会很高,致使并发度大打折扣。不过在某些特定的场景中,表级锁也可以有良好的性能。例如,READ LOCAL 表级锁支持某些类型的并发写操作。另外,写锁也比读锁有更高的优先级,因此一个写锁请求可能会**入到读锁队列的前面(写锁可以插入到锁队列中读锁的前面,反之读锁则不能插入到写锁的前面)。使用表级锁的主要是 MyISAM,MEMORY,CSV 等一些非事务性存储引擎。尽管存储引擎可以管理自己的锁,MySQL 本身还是会使用各种有效的表级锁来实现不同的目的。例如,服务器会为诸如 ALTER TABLE 之类的语句使用表级锁,而忽略存储引擎的锁机制。2)页级锁(page lock)页级锁是 MySQL 中比较独特的一种锁定级别,在其他数据库管理软件中并不常见。页级锁的颗粒度介于行级锁与表级锁之间,所以获取锁定所需要的资源开销,以及所能提供的并发处理能力同样也是介于上面二者之间。另外,页级锁和行级锁一样,会发生死锁。页级锁主要应用于 BDB 存储引擎。3)行级锁(row lock)行级锁的锁定颗粒度在 MySQL 中是最小的,只针对操作的当前行进行加锁,所以行级锁发生锁定资源争用的概率也最小。行级锁能够给予应用程序尽可能大的并发处理能力,从而提高需要高并发应用系统的整体性能。虽然行级锁在并发处理能力上面有较大的优势,但也因此带来了不少弊端。由于锁定资源的颗粒度很小,所以每次获取锁和释放锁需要做的事情也就更多,带来的消耗自然也就更大。此外,行级锁也最容易发生死锁。所以说行级锁最大程度地支持并发处理的同时,也带来了最大的锁开销。行级锁主要应用于 InnoDB 存储引擎。随着锁定资源颗粒度的减小,锁定相同数据量的数据所需要消耗的内存数量也越来越多,实现算法也会越来越复杂。不过,随着锁定资源颗粒度的减小,应用程序的访问请求遇到锁等待的可能性也会随之降低,系统整体并发度也会随之提升。MySQL 这 3 种锁的特性可大致归纳如下: 表级锁行级锁页级锁开销小大介于表级锁和行级锁之间加锁快慢介于表级锁和行级锁之间死锁不会出现死锁会出现死锁会出现死锁锁粒度大小介于表级锁和行级锁之间并发度低高一般从上述特点可见,很难笼统的说哪种锁更好,只能具体应用具体分析。从锁的角度来说,表级锁适合以查询为主,只有少量按索引条件更新数据的应用,如 Web 应用。而行级锁更适合于有大量按索引条件,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。
-
转载https://blog.csdn.net/weixin_43458965/article/details/108844967?utm_medium=distribute.pc_category.none-task-blog-hot-9.nonecase&depth_1-utm_source=distribute.pc_category.none-task-blog-hot-9.nonecase&request_id=无脑Mysql安装教程1.去官网下载Mysql2.解压Mysql3.配置环境变量4.修改配置文件5.运行CMD(win+R,输入cmd回车确认即可)6.执行命令1.去官网下载MysqlMysql下载地址2.解压Mysql在电脑上随便找一个位置创建个文件夹,将mysql解压到里面即可(建议D盘)3.配置环境变量复制解压后mysql的bin路径,然后配置环境变量在path路径新建一个,直接将路径输入即可4.修改配置文件找到刚才解压mysql的目录文件修改my.ini配置文件主要就是修改里面的basedir与datadir如果没有就手动添加basedir:设置为你的mysql的安装目录datadir:设置为你的数据存放目录目录位置直接找到文件夹复制即可5.运行CMD(win+R,输入cmd回车确认即可)以管理员身份运行cmd(一定要用管理员身份运行,不然权限不够)输入cd命令跳转到mysql的bin目录6.执行命令1.输入mysqld -install 1如果执行成功就会显示2.启动服务,输入 net start mysql13.服务启动,输入 mysql -u root -p1第一次登录没有密码,直接按回车过回车后显示mysql> 即代表创建成功4.成功进入后可以修改mysql密码 输入:alter user 'root'@'localhost' identified by '123456'; by后面就是要修改成的密码
-
查看MySQL提供的所有存储引擎mysql> show engines;查看MySQL提供的所有存储引擎从上图我们可以查看出 MySQL 当前默认的存储引擎是InnoDB,并且在5.7版本所有的存储引擎中只有 InnoDB 是事务性存储引擎,也就是说只有 InnoDB 支持事务。查看MySQL当前默认的存储引擎我们也可以通过下面的命令查看默认的存储引擎。mysql> show variables like '%storage_engine%';查看表的存储引擎show table status like “table_name” ; 查看表的存储引擎 MyISAM和InnoDB区别MyISAM是MySQL的默认数据库引擎(5.5版之前)。虽然性能极佳,而且提供了大量的特性,包括全文索引、压缩、空间函数等,但MyISAM不支持事务和行级锁,而且最大的缺陷就是崩溃后无法安全恢复。不过,5.5版本之后,MySQL引入了InnoDB(事务性数据库引擎),MySQL 5.5版本后默认的存储引擎为InnoDB。大多数时候我们使用的都是 InnoDB 存储引擎,但是在某些情况下使用 MyISAM 也是合适的比如读密集的情况下。(如果你不介意 MyISAM 崩溃恢复问题的话)。两者的对比:是否支持行级锁 : MyISAM 只有表级锁(table-level locking),而InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。是否支持事务和崩溃后的安全恢复: MyISAM强调的是性能,每次查询具有原子性,其执行速度比InnoDB类型更快,但是不提供事务支持。但是InnoDB提供事务支持,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。是否支持外键: MyISAM不支持,而InnoDB支持。是否支持MVCC :仅 InnoDB 支持。应对高并发事务, MVCC比单纯的加锁更高效;MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作;MVCC可以使用 乐观(optimistic)锁 和悲观(pessimistic)锁来实现;各数据库中MVCC实现并不统一。
-
一、问题阐述root@mysqldb 22:12: [xucl]> show create table t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `id` varchar(255) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) root@mysqldb 22:19: [xucl]> select * from t1; +--------------------+ | id | +--------------------+ | 204027026112927605 | | 204027026112927603 | | 2040270261129276 | | 2040270261129275 | | 100 | | 101 | +--------------------+ 6 rows in set (0.00 sec)现象:root@mysqldb 22:19: [xucl]> select * from t1 where id=204027026112927603; +--------------------+ | id | +--------------------+ | 204027026112927605 | | 204027026112927603 | +--------------------+ 2 rows in set (0.00 sec)结果的显示是204027026112927603,为什么204027026112927605也出来了二、源码解释堆栈调用关系如下所示: 其中JOIN::exec()是执行的入口,Arg_comparator::compare_real()是进行等值判断的函数,其定义如下int Arg_comparator::compare_real() { /* Fix yet another manifestation of Bug#2338. 'Volatile' will instruct gcc to flush double values out of 80-bit Intel FPU registers before performing the comparison. */ volatile double val1, val2; val1= (*a)->val_real(); if (!(*a)->null_value) { val2= (*b)->val_real(); if (!(*b)->null_value) { if (set_null) owner->null_value= 0; if (val1 < val2) return -1; if (val1 == val2) return 0; return 1; } } if (set_null) owner->null_value= 1; return -1; }比较步骤如下图所示,逐行读取t1表的id列放入val1,而常量204027026112927603存在于cache中,类型为double类型(2.0402702611292762E+17),所以到这里传值给val2后val2=2.0402702611292762E+17。 当扫描到第一行时,204027026112927605转成doule的值为2.0402702611292762e17,等式成立,判定为符合条件的行,继续往下扫描,同理204027026112927603也同样符合 如何检测string类型的数字转成doule类型是否溢出呢?这里经过测试,当数字超过16位以后,转成double类型就已经不准确了,例如20402702611292711会表示成20402702611292712(如图中val1) MySQL string转成double的定义函数如下:{ char buf[DTOA_BUFF_SIZE]; double res; DBUG_ASSERT(end != NULL && ((str != NULL && *end != NULL) || (str == NULL && *end == NULL)) && error != NULL); res= my_strtod_int(str, end, error, buf, sizeof(buf)); return (*error == 0) ? res : (res < 0 ? -DBL_MAX : DBL_MAX); }真正转换函数my_strtod_int位置在dtoa.c/* strtod for IEEE--arithmetic machines. This strtod returns a nearest machine number to the input decimal string (or sets errno to EOVERFLOW). Ties are broken by the IEEE round-even rule. Inspired loosely by William D. Clinger's paper "How to Read Floating Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. Modifications: 1. We only require IEEE (not IEEE double-extended). 2. We get by with floating-point arithmetic in a case that Clinger missed -- when we're computing d * 10^n for a small integer d and the integer n is not too much larger than 22 (the maximum integer k for which we can represent 10^k exactly), we may be able to compute (d*10^k) * 10^(e-k) with just one roundoff. 3. Rather than a bit-at-a-time adjustment of the binary result in the hard case, we use floating-point arithmetic to determine the adjustment to within one bit; only in really hard cases do we need to compute a second residual. 4. Because of 3., we don't need a large table of powers of 10 for ten-to-e (just some small tables, e.g. of 10^k for 0 <= k <= 22). */既然是这样,我们测试下没有溢出的案例root@mysqldb 23:30: [xucl]> select * from t1 where id=2040270261129276; +------------------+ | id | +------------------+ | 2040270261129276 | +------------------+ 1 row in set (0.00 sec) root@mysqldb 23:30: [xucl]> select * from t1 where id=101; +------+ | id | +------+ | 101 | +------+ 1 row in set (0.00 sec)结果符合预期,而在本例中,正确的写法应当是root@mysqldb 22:19: [xucl]> select * from t1 where id='204027026112927603'; +--------------------+ | id | +--------------------+ | 204027026112927603 | +--------------------+ 1 row in set (0.01 sec)三、结论避免发生隐式类型转换,隐式转换的类型主要有字段类型不一致、in参数包含多个类型、字符集类型或校对规则不一致等隐式类型转换可能导致无法使用索引、查询结果不准确等,因此在使用时必须仔细甄别数字类型的建议在字段定义时就定义为int或者bigint,表关联时关联字段必须保持类型、字符集、校对规则都一致
-
索引的分类1、索引我们分为四类来讲 单列索引(普通索引,唯一索引,主键索引)、组合索引、全文索引、空间索引、1.1、单列索引:一个索引只包含单个列,但一个表中可以有多个单列索引。 这里不要搞混淆了。1.1.1、普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。1.1.2、唯一索引:索引列中的值必须是唯一的,但是允许为空值,1.1.3、主键索引:是一种特殊的唯一索引,不允许有空值。1.2、组合索引在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。这个如果还不明白,等后面举例讲解时在细说1.3、全文索引全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引,介绍了要求,说说什么是全文索引,就是在一堆文字中,通过其中的某个关键字等,就能找到该字段所属的记录行,比如有"你是个大煞笔,二货 …" 通过大煞笔,可能就可以找到该条记录。这里说的是可能,因为全文索引的使用涉及了很多细节,我们只需要知道这个大概意思,如果感兴趣进一步深入使用它,那么看下面测试该索引时,会给出一个博文,供大家参考。1.4、空间索引空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。在创建空间索引时,使用SPATIAL关键字。要求,引擎为MyISAM,创建空间索引的列,必须将其声明为NOT NULL。具体细节看下面sql 优化和常见索引失效的情况在sql查询中为了提高查询效率,我们常常会采取一些措施对查询语句进行sql优化,下面总结的一些方法,有需要的可以参考参考。1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=03.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num=10 or num=20可以这样查询:select id from t where num=10union allselect id from t where num=205.in 和 not in 也要慎用,否则会导致全表扫描,如:select id from t where num in(1,2,3)对于连续的数值,能用 between 就不要用 in 了:select id from t where num between 1 and 36.下面的查询也将导致全表扫描:select id from t where name like ‘%abc%’7.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:select id from t where num/2=100应改为:select id from t where num=100*28.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:select id from t where substring(name,1,3)=‘abc’–name以abc开头的id应改为:select id from t where name like ‘abc%’9.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。10.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。11.不要写一些没有意义的查询,如需要生成一个空表结构:select col1,col2 into #t from t where 1=0这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:create table #t(…)12.很多时候用 exists 代替 in 是一个好的选择:select num from a where num in(select num from b)用下面的语句替换:select num from a where exists(select 1 from b where num=a.num)13.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。14.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。15.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。16.尽可能的使用 varchar 代替 char ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。17.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。18.避免频繁创建和删除临时表,以减少系统表资源的消耗。19.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。20.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。21.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。22.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。23.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。24.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。25.尽量避免大事务操作,提高系统并发能力。26.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
-
在 MySQL 中,InnoDB 行锁通过给索引上的索引项加锁来实现,如果没有索引,InnoDB 将通过隐藏的聚簇索引来对记录加锁。InnoDB 支持 3 种行锁定方式:行锁(Record Lock):直接对索引项加锁。间隙锁(Gap Lock):锁加在索引项之间的间隙,也可以是第一条记录前的“间隙”或最后一条记录后的“间隙”。Next-Key Lock:行锁与间隙锁组合起来用就叫做 Next-Key Lock。 前两种的组合,对记录及其前面的间隙加锁。默认情况下,InnoDB 工作在可重复读(默认隔离级别)下,并且以 Next-Key Lock 的方式对数据行进行加锁,这样可以有效防止幻读的发生。Next-Key Lock 是行锁与间隙锁的组合,这样,当 InnoDB 扫描索引项的时候,会首先对选中的索引项加上行锁(Record Lock),再对索引项两边的间隙(向左扫描扫到第一个比给定参数小的值, 向右扫描扫到第一个比给定参数大的值, 然后以此为界,构建一个区间)加上间隙锁(Gap Lock)。如果一个间隙被事务 T1 加了锁,其它事务不能在这个间隙插入记录。 要禁止间隙锁的话,可以把隔离级别降为读已提交(READ COMMITTED),或者开启参数 innodb_locks_unsafe_for_binlog。注意:以上语句描述的情况,与 MySQL 所设置的事务隔离级别有较大的关系。开启一个事务时,InnoDB 存储引擎会在更新的记录上加行级锁,此时其它事务不可以更新被锁定的记录。下面我们以示例1演示此过程。例 下面的语句需要在两个命令行窗口中执行。为了方便理解,我们分别称之为 A 窗口和 B 窗口。分别在 A 窗口和 B 窗口中查看事务隔离级别,A 窗口和 B 窗口的事务隔离级别需要保持一致。A 窗口查看隔离级别的 SQL 语句和运行结果如下所示:mysql> SHOW VARIABLES LIKE 'tx_isolation' \G *************************** 1. row *************************** Variable_name: tx_isolation Value: REPEATABLE-READ 1 row in set, 1 warning (0.03 sec)B 窗口查看隔离级别 SQL 语句和运行结果如下所示:mysql> SHOW VARIABLES LIKE 'tx_isolation' \G *************************** 1. row *************************** Variable_name: tx_isolation Value: REPEATABLE-READ 1 row in set, 1 warning (0.03 sec)结果显示,A窗口和 B窗口的事务隔离级别都为 REPEATABLE-READ。在 A窗口中开启一个事务,并修改 tb_student 表,SQL 语句和运行结果如下:mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> UPDATE test.tb_student SET age ='30' WHERE id = 1; Query OK, 1 row affected (0.02 sec) Rows matched: 1 Changed: 1 Warnings: 0在 B窗口中也开启一个事务,并修改 tb_student 表,SQL 语句和运行结果如下:mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> UPDATE test.tb_student SET age ='30' WHERE id = 1;会发现 UPDATE 语句一直在执行。这时我们在 A 窗口中提交事务。mysql> COMMIT; Query OK, 0 rows affected (0.01 sec)这时我们发现 B 窗口中的 UPDATE 语句执行成功。mysql> UPDATE test.tb_student SET age ='30' WHERE id = 1; Query OK, 0 rows affected (1 min 2.78 sec) Rows matched: 1 Changed: 0 Warnings: 0查询 tb_student 表中的数据,SQL 语句和运行结果如下:mysql> SELECT * FROM test.tb_student; +----+------+------+------+------+ | id | name | age | sex | num | +----+------+------+------+------+ | 1 | 张三 | 30 | 男 | 4 | | 2 | 李四 | 12 | 男 | 4 | | 3 | 王五 | 13 | 女 | 4 | | 4 | 张四 | 13 | 女 | 4 | | 5 | 王四 | 15 | 男 | 4 | | 6 | 赵六 | 12 | 女 | 4 | +----+------+------+------+------+ 6 rows in set (0.00 sec)如以上实例所示,当有不同的事务同时更新同一条记录时,另外一个事务需要等待另一个事务把锁释放,此时查看 MySQL 中 InnoDB 存储引擎的状态如下:mysql> SHOW ENGINE innodb status \G ...... ------------ TRANSACTIONS ------------ Trx id counter 19556 Purge done for trx's n:o < 19554 undo n:o < 0 state: running but idle History list length 12 LIST OF TRANSACTIONS FOR EACH SESSION: ---TRANSACTION 283572223909376, not started 0 lock struct(s), heap size 1136, 0 row lock(s) ---TRANSACTION 19555, ACTIVE 54 sec starting index read mysql tables in use 1, locked 1 LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s) MySQL thread id 14, OS thread handle 4568, query id 886 localhost ::1 root updating UPDATE test.tb_student SET age ='30' WHERE id = 1 ------- TRX HAS BEEN WAITING 54 SEC FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 197 page no 3 n bits 80 index PRIMARY of table `test`.`tb_student` trx id 19555 lock_mode X locks rec but not gap waiting Record lock, heap no 2 PHYSICAL RECORD: n_fields 7; compact format; info bits 0 0: len 4; hex 80000001; asc ;; 1: len 6; hex 000000004c62; asc Lb;;从上面运行结果可以看出,SQL 语句 UPDATE test.tb_student SET age ='30' WHERE id = 1 在等待,RECORD LOCKS space id 197 page no 3 n bits 80 index PRIMARY of table `test`.`tb_student` trx id 19555 lock_mode X locks rec but not gap 表示锁住的资源,locks rec but not gap 代表锁住的是一个索引,不是一个范围。“MySQL thread id 14, OS thread handle 4568, query id 886 localhost ::1 root updating”表示第 2 个事务连接的 ID 为 14,当前状态为正在更新,同时正在更新的记录需要等待其它事务将锁释放。当超过事务等待锁允许的最大时间,此时会提示“ERROR 1205(HY000):Lock wait timeout exceeded; try restarting transaction" 及当前事务执行失败,则自动执行回滚操作。MySQL 数据库采用 InnoDB 模式,默认参数 innodb_lock_wait_timeout 设置锁等待的时间是 50s,一旦数据库锁超过这个时间就会报错。可通过以下命令查看当前数据库锁等待的时间。mysql> SHOW GLOBAL VARIABLES LIKE 'innodb_lock_wait_timeout'; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | innodb_lock_wait_timeout | 120 | +--------------------------+-------+ 1 row in set, 1 warning (0.02 sec)下面演示了 InnoDB 间隙锁的实现机制。例 下面在保证 A 窗口和 B 窗口的前提下,将 tb_student 表中的 id 字段设为外键,并开启一个事务,修改 tb_student 表中 id 为 1 的 age。SQL 语句和运行结果如下:mysql> ALTER TABLE test.tb_student ADD unique key idx_id(id); Query OK, 0 rows affected (0.17 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> UPDATE test.tb_student SET age ='31' WHERE id = 1; Query OK, 0 rows affected (0.01 sec) Rows matched: 1 Changed: 0 Warnings: 0在 B 窗口中开启一个事务,修改 tb_student 表中 id 为 2 的 age,SQL 语句和运行结果如下:mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> UPDATE test.tb_student SET age ='28'WHERE id=2; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0这时分别提交 A窗口和 B窗口的事务。mysql> COMMIT; Query OK, 0 rows affected (0.01 sec)查询 tb_student 表的数据,SQL 语句和运行结果如下:mysql> SELECT * FROM test.tb_student; +----+------+------+------+------+ | id | name | age | sex | num | +----+------+------+------+------+ | 1 | 张三 | 31 | 男 | 4 | | 2 | 李四 | 28 | 男 | 4 | | 3 | 王五 | 13 | 女 | 4 | | 4 | 张四 | 13 | 女 | 4 | | 5 | 王四 | 15 | 男 | 4 | | 6 | 赵六 | 12 | 女 | 4 | +----+------+------+------+------+ 6 rows in set (0.00 sec)在上述示例中,由于 InnoDB 行级锁为间隙锁,只锁定需要的记录,因此 B窗口中的事务可以更新其它记录,两个事务之间互不影响。
-
麻雀虽小,五脏俱全。MySQL 虽然以简单著称,但其内部结构并不简单,本节主要介绍 MySQL 的整体架构组成。学习 MySQL 就好比盖房子,如果想把房子盖的特别高,地基一定要稳,基础一定要牢固。学习 MySQL 数据库前要先了解它的体系结构,这是学好 MySQL 数据库的前提。 MySQL 由连接池、SQL 接口、解析器、优化器、缓存、存储引擎等组成,可以分为三层,即 MySQL Server 层、存储引擎层和文件系统层。MySQL Server 层又包括连接层和 SQL 层。如下是官方文档中 MySQL 的基础架构图:MySQL基础架构图上图中,Connection pool 为连接层,Management Services & Utilities ...Caches & Buffers 为 SQL 层,Pluggable Storage Engines 为存储引擎层,File system、Files & Logs 为文件系统层。Connectors 不属于以上任何一层,可以将 Connectors 理解为各种客户端、应用服务,主要指的是不同语言与 SQL 的交互。1. 连接层应用程序通过接口(如 ODBC、JDBC)来连接 MySQL,最先连接处理的是连接层。连接层包括通信协议、线程处理、用户名密码认证 3 部分。通信协议负责检测客户端版本是否兼容 MySQL 服务端。线程处理是指每一个连接请求都会分配一个对应的线程,相当于一条 SQL 对应一个线程,一个线程对应一个逻辑 CPU,在多个逻辑 CPU 之间进行切换。密码认证用来验证用户创建的账号、密码,以及 host 主机授权是否可以连接到 MySQL 服务器。Connection Pool(连接池)属于连接层。由于每次建立连接都需要消耗很多时间,连接池的作用就是将用户连接、用户名、密码、权限校验、线程处理等需要缓存的需求缓存下来,下次可以直接用已经建立好的连接,提升服务器性能。2. SQL层SQL 层是 MySQL 的核心,MySQL 的核心服务都是在这层实现的。主要包含权限判断、查询缓存、解析器、预处理、查询优化器、缓存和执行计划。权限判断可以审核用户有没有访问某个库、某个表,或者表里某行数据的权限。查询缓存通过 Query Cache 进行操作,如果数据在 Query Cache 中,则直接返回结果给客户端,不必再进行查询解析、优化和执行等过程。查询解析器针对 SQL 语句进行解析,判断语法是否正确。预处理器对解析器无法解析的语义进行处理。查询优化器对 SQL 进行改写和相应的优化,并生成最优的执行计划,就可以调用程序的 API 接口,通过存储引擎层访问数据。Management Services & Utilities、SQL Interface、Parser、Optimizer 和 Caches & Buffers 属于 SQL 层,详细说明如下表所示。名称说明Management Services & Utilities MySQL 的系统管理和控制工具,包括备份恢复、MySQL 复制、集群等。SQL Interface(SQL 接口)用来接收用户的 SQL 命令,返回用户需要查询的结果。例如 SELECT FROM 就是调用 SQL Interface。Parser(查询解析器)在 SQL 命令传递到解析器的时候会被解析器验证和解析,以便 MySQL 优化器可以识别的数据结构或返回 SQL 语句的错误。Optimizer(查询优化器)SQL 语句在查询之前会使用查询优化器对查询进行优化,同时验证用户是否有权限进行查询,缓存中是否有可用的最新数据。它使用“选取-投影-连接”策略进行查询。例如 SELECT id, name FROM student WHERE gender = "女";语句中,SELECT 查询先根据 WHERE 语句进行选取,而不是将表全部查询出来以后再进行 gender 过滤。SELECT 查询先根据 id 和 name 进行属性投影,而不是将属性全部取出以后再进行过滤,将这两个查询条件连接起来生成最终查询结果。Caches & Buffers(查询缓存)如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。这个缓存机制是由一系列小缓存组成的,比如表缓存、记录缓存、key 缓存、权限缓存等。3. 存储引擎层Pluggable Storage Engines 属于存储引擎层。存储引擎层是 MySQL 数据库区别于其他数据库最核心的一点,也是 MySQL 最具特色的一个地方。主要负责 MySQL 中数据的存储和提取。因为在关系数据库中,数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型(即存储和操作此表的类型)。4. 文件系统层文件系统层主要是将数据库的数据存储在操作系统的文件系统之上,并完成与存储引擎的交互。
-
查询所有数据库的总大小方法如下:mysql> use information_schema; mysql> select concat(round(sum(DATA_LENGTH/1024/1024),2),'MB') as data from TABLES; +-----------+ | data | +-----------+ | 3052.76MB | +-----------+ 1 row in set (0.02 sec)统计一下所有库数据量每张表数据量=AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTHSELECT SUM(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH)/1024/1024 AS total_mb FROM information_schema.TABLES统计每个库大小:SELECT table_schema,SUM(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH)/1024/1024 AS total_mb FROM information_schema.TABLES group by table_schema;第二种情况:查看指定数据库的大小,比如说:数据库test,方法如下:mysql> use information_schema; mysql> select concat(round(sum(DATA_LENGTH/1024/1024),2),'MB') as data from TABLES where table_schema='test'; +----------+ | data | +----------+ | 142.84MB | +----------+ 1 row in set (0.00 sec)1.查看所有数据库各容量大小select table_schema as '数据库', sum(table_rows) as '记录数', sum(truncate(data_length/1024/1024, 2)) as '数据容量(MB)', sum(truncate(index_length/1024/1024, 2)) as '索引容量(MB)' from information_schema.tables group by table_schema order by sum(data_length) desc, sum(index_length) desc;2.查看所有数据库各表容量大小select table_schema as '数据库', table_name as '表名', table_rows as '记录数', truncate(data_length/1024/1024, 2) as '数据容量(MB)', truncate(index_length/1024/1024, 2) as '索引容量(MB)' from information_schema.tables order by data_length desc, index_length desc;3.查看指定数据库容量大小例:查看mysql库容量大小 select table_schema as '数据库', sum(table_rows) as '记录数', sum(truncate(data_length/1024/1024, 2)) as '数据容量(MB)', sum(truncate(index_length/1024/1024, 2)) as '索引容量(MB)' from information_schema.tables where table_schema='mysql'; 4.查看指定数据库各表容量大小例:查看mysql库各表容量大小 select table_schema as '数据库', table_name as '表名', table_rows as '记录数', truncate(data_length/1024/1024, 2) as '数据容量(MB)', truncate(index_length/1024/1024, 2) as '索引容量(MB)' from information_schema.tables where table_schema='mysql' order by data_length desc, index_length desc;题外方法直接用shell命令统计mysql data目录中的大小(注意只有库,不包含数据库日志大小)备注 :data_length :存储数据大小data_length/1024/1024:将字节转换为MBround(sum(data_length/1024/1024),2):取两位小数concat(round(sum(data_length/1024/1024),2),'MB') :给计算结果追加单位 “MB”
-
-
-
与其它数据库不同,MySQL 服务器可以在不同的 SQL 模式下运行,并且可以针对不同的客户端以不同的方式应用这些模式,具体取决于 sql_mode 系统变量的值。 SQL 模式定义了 MySQL 数据库所支持的 SQL 语法和数据校验(数据验证检查),这样可以更容易的在不同环境下使用 MySQL。 在 MySQL 中,SQL 模式常用来解决下面几类问题:通过设置 SQL Mode,可以完成不同严格程度的数据校验,有效地保障了数据的准确性。通过设置 SQL Mode 为 ANSI 模式,可以保证大多数 SQL 符合标准的 SQL 语法,使不同数据库之间进行迁移时,不需要进行较大的修改。在不同数据库之间进行数据迁移之前,设置 SQL Mode 可以使 MySQL 中的数据更方便地迁移到目标数据库中。sql_mode 系统变量的常用值下面列出了几种 SQL 模式常用的值。1) TRICT_ ALL_TABLES 和 STRICT_ TRANS_TABLES如果将 sql_mode 的值设置为 TRICT_ALL_TABLES 和 STRICT_TRANS_TABLES,那么 MySQL将启用“严格”模式。在严格模式下,MySQL 服务器会更加严格地对待接收到的不合格数据,它不会把这些不合格的数据转换为最为接近的有效值,而是会拒绝接收它们。简单来说 MySQL 的严格模式就是 MySQL 自身对数据进行的严格校验,例如格式、长度和类型等。2) TRADITIONAL类似于严格模式,但是对于插入的不合格值会给出错误而不是警告。可以应用在事务表和非事务表,用于事务表时,只要出现错误就会立即回滚。如果你使用的是非事务存储引擎,建议不要把 SQL Mode 值设置为 TRADITIONAL,因为出现错误前进行的操作不会回滚,这样会导致操作只进行了一部分。3) ANSI_QUOTESMySQL 服务器会把双引号识别为一个标识符引用字符,而不是字符串的引号字符。所以在启用 ANSI_QUOTES 时,不能用双引号来引用字符串。4) PIPES_ AS_ CONCAT会让 MySQL 服务器把||当成一个标准的 SQL 字符串连接运算符,而不会把它当成是 OR 运算符的同义词。在 Oracle 等数据库中,||被视为字符串的连接操作符,所以在其它数据库中含有||操作符的 SQL 在 MySQL 中将无法执行,为了解决这个问题,MySQL 提供了这个值。5) ANSI会同时启用 ANSI_QUOTES、PIPES_ AS_CONCAT 和其它的几个模式值,使 MySQL 服务器的行为比它的默认运行状态更接近于标准 SQL。如何设置 sql_mode在设置 SQL 模式时,需要指定一个由单个模式值或多个模式值(多个模式值用逗号分隔)构成的值,或者指定一个空字符串,用以清除该值。模式值不区分大小写。 如果想在启动服务器时设置 SQL 模式,那么可以在 mysqld 命令行,或者在某个选项文件里设置系统变量 sql_mode。可以使用下面语句:sql_mode= "TRADITIONAL "sql_mode= "ANSI_ QUOTES, PIPES_ AS_ CONCAT"如果只是想在运行时更改 SQL 模式,那么可以使用 SET 语句来设置 sql_mode 系统变量。SET sql_mode = ' TRADITIONAL' ; 如果想设置全局性的 SQL 模式,则需要加上 GLOBAL 关键字:SET GLOBAL sql_mode = ' TRADITIONAL';设置全局变量需要具备 SUPER 管理权限。新设置的全局变量值将成为此后连入客户端的默认 SQL 模式。 如果想获取当前会话或全局的 SQL 模式值,则可以使用如下语句:SELECT @@SESSION.sql_mode;SELECT @@GLOBAL. sql_mode;其返回值由当前启用的所有模式构成,两个模式之间以逗号隔开。如果当前没有启用任何模式,则返回一个空值。
-
简而言之,性能优化就是在不影响系统能正确运行的前提下,运行速度更快,完成特定功能所需的时间更短。我们可以通过某些有效的方法来提高 MySQL 数据库的性能,目的是让 MySQL 数据库的运行速度更快、占用的磁盘空间更小。性能优化包括很多方面,例如优化查询速度、优化更新速度和优化 MySQL 服务器等。通过不同的优化方式达到提高 MySQL 数据库性能的目的。优化数据库是数据库管理员和开发人员的必备技能。下面将为读者介绍优化的基本知识。MySQL 数据库的用户和数据非常少时,很难判断数据库性能的好坏。只有当长时间运行,并且有大量用户进行频繁操作时,MySQL 数据库的性能才能体现出来。例如,一个每天有几万用户同时在线的大型网站,它的数据库性能的优劣就很明显。这么多用户同时连接 MySQL 数据库,并且进行查询、插入和更新的操作。如果 MySQL 数据库的性能很差,很可能无法承受如此多用户的同时操作。另外,如果用户查询一条记录需要花费很长时间,那么用户很难会喜欢这个网站。因此,为了提高 MySQL 数据库的性能,需要进行一系列的优化措施。一方面是找出系统的瓶颈,提高 MySQL 数据库整体的性能,另一方面需要合理的数据库结构设计和参数调整,来提高用户操作响应的速度,同时还要尽可能节省系统资源,以便系统可以提供更大负荷的服务。例如,通过优化文件系统,提高磁盘 I\O 的读写速度;通过优化操作系统调度策略,提高 MySQL 在高负荷情况下的负载能力;优化表结构、索引、查询语句等使查询响应更快。如果 MySQL 数据库中需要进行大量的查询操作,那么就需要对查询语句进行优化。对于耗费时间的查询语句进行优化,可以提高整体的查询速度。如果连接 MySQL 数据库的用户很多,那么就需要对 MySQL 服务器进行优化。否则,大量的用户同时连接 MySQL 数据库,可能会造成数据库系统崩溃。那么我们应该如何进行系统的分析,来尽快定位效率低下的 SQL 呢?主要有以下两种方法:1. 使用 SHOW STATUS 命令数据库管理员可以使用 SHOW STATUS 语句查询 MySQL 数据库的性能参数,了解各种 SQL 的执行频率。语法形式如下:SHOW STATUS LIKE 'value';其中,value 参数是常用的几个统计参数,常用参数介绍如下:Connections:连接 MySQL 服务器的次数;Uptime:MySQL 服务器的上线时间;Slow_queries:慢查询的次数;Com_select:查询操作的次数;Com_insert:插入操作的次数,对于批量插入操作,只累加一次;Com_update:更新操作的次数;Com_delete:删除操作的次数。以上参数针对于所有存储引擎的表,下面几个参数只针对 InnoDB 存储引擎。Innodb_rows_read:表示 SELECT 语句查询的记录数;Innodb_rows_inserted:表示 INSERT 语句插入的记录数;Innodb_rows_updated:表示 UPDATE 语句更新的记录数;Innodb_rows_deleted:表示 DELETE 语句删除的记录数。比如,需要查询 MySQL 服务器的连接次数,可以执行下面的 SHOW STATUS 语句:SHOW STATUS LIKE 'Connections';查询其它参数的方法和以上参数的查询方法相同。通过以上几个参数,可以很容易的了解当前数据库的应用是以插入为主还是以查询为主,以及各种类型的 SQL 语句的大致执行比例。然后根据分析结果,进行相应的性能优化。2. 使用慢查询日志慢查询次数参数可以结合慢查询日志,找出慢查询语句,然后针对慢查询语句进行表结构优化或者查询语句优化。
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签