服务器崩溃!原因竟是mysql查询? (mysql查询导致服务器崩溃)

今天,我们的服务器突然宕机了,这是一个相当严重的问题,因为服务器是我们工作的命脉。经过仔细排查,我们发现这个问题的根源竟然是由一个mysql查询引起的。

那么,究竟是什么样的查询语句导致了这样的崩溃呢?

我们需要了解一下什么是mysql查询。MySQL是一种流行的关系型数据库管理系统,用户可以通过它来操作数据库并执行各种查询操作。查询通常涉及对数据库中的数据进行搜索、排序、聚合等操作,以获取所需的结果集。

然而,在某些情况下,查询可能会变得无法控制,尤其是在大型数据集上进行操作时。这是因为查询需要耗费大量的计算资源和内存,从而使服务器负载过高,并超出了其处理能力的限制。如果这种负载持续时间较长,那么服务器就会崩溃。

回到我们的故事中来,我们的服务器崩溃的原因是一条查询语句只能影响几百行记录,但是实际上它遍历了整个数据集,耗尽了服务器的资源。由于我们的数据集非常庞大,这个查询语句导致了服务器崩溃和数据丢失的风险。

这种情况在 MySQL 中很常见,因为它的执行引擎的选择、索引失效等因素都会影响查询的性能。为此,我们需要在编写查询语句时更加小心谨慎,避免出现类似的问题。

针对这一问题,我们需要采取一些措施来预防,例如:

1. 优化查询语句:

在编写查询语句时,我们需要清楚自己的意图,并尽可能地使用索引来加速查询。同时,我们还需要注意避免使用嵌套查询语句,因为它们往往会导致峰值负载。

2. 升级硬件配置:

如果我们的硬件配置比较低(例如,RAM 容量过小),那么查询操作可能会超出服务器的处理能力。在这种情况下,我们需要考虑升级硬件配置,提高服务器的性能。

3. 分散负载:

如果我们的服务器负载过高,那么我们可以使用集群或分布式架构来分散负载,从而实现更好的性能和稳定性。

服务器突然宕机所引起的一切问题,都给我们敲响了预防意识的警钟。通过本次故障经历,我们认识到了MySQL 查询语句的重要性,以及在服务器管理中优化查询语句的必要性。这也提醒了我们,在日常生活中,我们也要时刻保持警觉,随时发现并解决问题,从而更好地应对各种挑战。

相关问题拓展阅读:

mysql运行一段时间,TOMCAT服务器就会一直报这个错误,修改了MYSQL数据库的配置,但没有用,在线等

一、Can’t connect to MySQL server on ‘localhost’ (10061)

翻译:不能连接到 localhost 上的mysql

分析:这说明“localhost”计算机是存在的,但在这台机器上却没提供MySQL服务。

需要启动这台机器上的MySQL服务,如果机子负载太高没空相应请求也会产生这个错误。

解决:既然没有纳森启动那就去启动这台机子的mysql。如果启动不成功,多数是因为你的my.ini配置的有问题。重新配置其即可。

如果觉得mysql负载异常,可以到mysql/bin 的目录下执行mysqladmin -uroot -p123 processlist来查看mysql当前的进程。

二、Unknown MySQL Server Host ‘localhosadst’ (11001)

翻译:未知的MySQL服务器 localhosadst

分析:服务器 localhosasdst 不存在。或者根本无法连接

解决:仔细检查自己论坛下面的 ./config.inc.php 找到$dbhost重新设置为正确的mysql 服务器地址。

三、Access denied for user: ‘roota@localhost’ (Using password: YES)

翻译:用户 roota 访问 localhost 被拒绝(没有允许通过)

分析:造成这个错误一般数据库用户名和密码相对mysql服务器不正确

解决:仔细检查自己论坛下面的 ./config.inc.php 找到$dbuser、$dbpw核实后重新设置保存即可。

四、Access denied for user: ‘red@localhost’ to database ‘newbbs’

翻译:用户 red 在localhost 服务器上没有权限操作数据库newbbs

分析:这个提示和问题三是不同的。那个是在连接数据库的时候就被阻止了,而这个错误是在对数据库进行操作时引起的。比如在select update等等。这个是因为该用户没有操作数据库相应的权力。比如select 这个操作在mysql.user.Select_priv里记录 Y 可以操作N 不可灶茄瞎以操作。

解决:如果是自己的独立主机那么更新mysql.user 的相应用户记录,比如这里要更新的用户为red 。或者直接修改 ./config.inc.php 为其配隐空置一个具有对数据库操作权限的用户

或者通过如下的命令来更新授权grant all privileges on dbname.* to ‘user’@’localhost’ identified by ‘password’

提示:更新了mysql库中的记录一定要重启mysql服务器才能使更新生效

FLUSH PRIVILEGES;

五、No Database Selected

翻译:没有数据库被选择上

分析:产生的原因有两种

config.inc.php 里面$dbname设置的不对。致使数据库根本不存在,所以在 $db->select_db($dbname); 时返回了false

和上面问题四是一样的,数据库用户没有select权限,同样会导致这样的错误。当你发现config.inc.php的设置没有任何问题,但还是提示这个错误,那一定就是这种情况了。

解决:对症下药

打开config.inc.php 找到$dbname核实重新配置并保存

同问题四的解决方法

六、Can’t open file: ‘_forums.MYI’. (errno: 145)

翻译:不能打开_forums.MYI

问题分析:

这种情况是不能打开 cdb_forums.MYI 造成的,引起这种情况可能的原因有:

1、服务器非正常关机,数据库所在空间已满,或一些其它未知的原因,对数据库表造成了损坏。

2、类 unix 操作系统下直接将数据库文件拷贝移动会因为文件的属组问题而产生这个错误。

解决方法:

1、修复数据表

可以使用下面的两种方式修复数据表:(之一种方法仅适合独立主机用户)

1)使用 myisamchk ,MySQL 自带了专门用户数据表检查和修复的工具 —— myisamchk 。更改当前目录到 MySQL/bin 下面,一般情况下只有在这个下面才能运行 myisamchk 命令。常用的修复命令为:myisamchk -r 数据文件目录/数据表名.MYI;

2)通过 phpMyAdmin 修复, phpMyAdmin 带有修复数据表的功能,进入到某一个表中后,点击“操作”,在下方的“表维护”中点击“修复表”即可。

注意:以上两种修复方式在执行前一定要备份数据库。

2、修改文件的属组(仅适合独立主机用户)

1)复制数据库文件的过程中没有将数据库文件设置为 MySQL 运行的帐号可读写(一般适用于 Linux 和 FreeBSD 用户)。

七、Table ‘test._sessions’ doesn’t exist

翻译:xx表不存在

分析:在执行sql语句时没有找到表,比如:SELECT * FROM _members WHERE uid=’XX’ 这里如果表_members不存在于$dbname库里,那么就会提示这个错误。具体可分为以下三种情况来讨论:

安装插件或者hack时修改了程序文件,而忘记了对数据库作相应的升级。

后台使用了不完全备份,导入数据时没有导入到已经安装了相应版本的论坛的数据库中。

解决: 同样对症下药,不同的原因不同的处理方法。

仔细对照插件作者提供的安装说明,把遗漏的对数据库的操作补上,如果仍然不能解决问题,那么应该怀疑该插件的可用性了。去咨询一下插件作者,或者将其卸载。

不要张冠李戴,多大的脚就穿多大的鞋。总之使得程序文件和数据库配套即可.

八、Unknown column ‘column_name’ in ‘field list’

翻译:未知的字段名 column_name

分析:在执行sql语句是出现了指定表中没有的字段名称,就会出现这个错误。具体导致的原因可分为以下两种

安装插件或者hack时修改了程序文件,而忘记了对数据库作相应的升级。

程序文件和数据库不配套,比如d2.5的数据库配置给d4.1的程序来用肯定会出现这个错误。

解决: 导致的原因和问题八的1和 3是相同的,所以解决方法也一样。

九、You have an error in your SQL syntax

翻译:有一个语法错误在你的sql中

分析:论坛标准的程序是没有sql语法错误的。所以造成这个错误的原因一般就两类

安装插件或擅自修改程序。

不同的数据库版本数据库导出导入,比如MySQL4.1的数据在导出的语句包含了MySQL4.0没有的功能,像字符集的设定,这时如果将这些sql导入到MySQL4.0的时候就会产生sql语法错误。

解决:

仔细检查看到底是哪里的错误,将其修正,实在不行就用标准程序把出错的程序替换。

在数据库备份的时候要留意,如果不打算倒入到其他版本的mysql中则不用特殊考虑,反之要特殊的设定。使用DZ4.1的后台数据备份,可以按照提示去设定想要的格式。独立主机的也可以在到处的时候将其导出为mysql4.0的格式。

mysqldump -uroot -p –default-character-set=latin1 –set-charset=gbk –skip-opt databse > test.sql

十、Duplicate entry ” for key 1

翻译:插入 使索引1重复

分析:索引如果是primary unique这两两种,那么数据表的数据对应的这个字段就必须保证其每条记录的唯一性。否则就会产生这个错误。

一般发生在对数据库写操作的时候,例如Discuz!4.1论坛程序要求所有会员的用户名username必须唯一,即username的索引是 unique,这时如果强行往cdb_members表里插入一个已有的username的记录就会发上这个错误,或者将一条记录的username更新 为已有的一个username。

改变表结构的时候也有可能导致这个错误。例如 Discuz!4.0论坛的数据库中cdb_members.username 的索引类型是index这个时候是允许有相同username的记录存在的,在升级到4.1的时候,因为要将username的索引由原来的index变 为unique。如果这时cdb_members里存在有相同的username的记录,那么就会引发这个错误。

导出数据据时有时会因为一些原因(作者目前还不清楚)导致同一条记录被重复导出,那么这个备份数据在导入的时候出现这个错误是在所难免的了。

修改了auto_increment的值,致使“下一个 Autoindex”为一条已经存在的记录

解决: 两种思路,一是破坏掉唯一性的索引。二是把重复的数据记录干掉,只保留一条。很显然之一种思路是不可取的。那么按照二的思路我们得出以下几种解决方法,对应上面的i ii iii

按照错误提示里的信息到数据库中将重复的记录删除,仅保留一条即可。之后继续执行升级操作。

这种情况发生的概率很小,可以用文本编辑器打开备份文档,查找重复的信息。将其多余的拿掉,仅保留一条即可。

查询出表中auto_increment更大的一条记录,设置auto_incerment比其大一即可。

PS:repaire table “表名“,可以暂时解决问题。

十一、 Duplicate key name ”

翻译:索引名重复

分析:要创建的索引已经存在了,就会引发这个错误,这个错误多发生在升级的时候。可能是已经升级过的,重复升级引起的错误。也有可能是之前用户擅自加的索引,刚好与升级文件中的所以相同了。

解决: 看看已经存在的索引和要添加的索引是否一样,一样的话可以跳过这条sql语句,如果不一样那么现删除已存在的所以,之后再执行。

十二、 Duplicate column name ”

翻译:字段名重复

分析:添加的字段已经存在,多发生在升级过程中,与问题十二的产生是一样的。

解决: 看一下已经存在的字段是否和将要添加的字段属性完全相同,如果相同则可以跳过不执行这句sql,如果不一样则删除掉这个字段。之后继续执行升级程序。

十三、 Table ” already exists

翻译:数据表已经存在

分析:表已经存在于库中,再次试图创建这个名字的表就会引发这个错误。同样多发生在论坛的升级中。类似于问题十二。

解决: 看看已经存在的表是否和将要创建的表完全一样,一样的话可以跳过不执行这个sql,否则请将存在的表先删除,之后继续执行升级文件。

十四、 Can’t create database ”. Database exists

翻译:不能创建数据库,数据库已经存在

分析:一个mysql下面的数据库名称必须保证唯一性,否则就会有这个错误。

解决:把已经存在的数据库改名或者把将要创建的数据库改名,总之不让他们的名称冲突。

十五、 小结(针对问题 11\12\13\14\15)

此类问题错误提示中都暗藏一个关键词duplicate(重复)

那么对于mysql数据库来说什么东西是不能重复的呢?

数据库 database

同一个数据库下数据表 table

同一个数据表下字段 column

同一个数据表下索引 key

同一个数据表在索引唯一(UNIQUE PRIMARY)的情况下记录中的这些字段不可以重复

十六、Unknown system variable ‘NAMES’

翻译:未知的系统变量NAMES

分析:Mysql版本不支持字符集设定,此时强行设定字符集就会出现这个错误。

解决: 将sql语句中的SET NAMES ‘’ 语句去掉

十七、 Lost connection to MySQL server during query

翻译:MySQL服务器失去连接在查询期间

分析:远程连接数据库是有时会有这个问题。MySQL服务器在执行一条sql语句的时候失去了连接造成的。

解决: 一般不需要怎么去处理,如果频繁的出现那么考虑改善硬件环境。

十八、User ‘red’ has exceeded the ‘max_updates’ resource (current value: 500)

翻译:msql用户red已经超过了’max_updates’(更大更新次数),’max_questions’(更大查询次数),’max_connections’(更大连接数),当前设定为500

分析:在mysql数据库的下有一个库为mysql,它其中有一个表为user这里面的纪录每一条都对应为一个mysql用户的授权。其中字段 max_questions max_updates max_connections分别记录着更大查询次数 更大更新数 更大连接数,当目前的任何一个参数大于任何一个设定的值就会产生这个错误。

解决: 独立主机用户可以直接修改授权表。修改完之后重启mysql或者跟新授权表,进入mysql提示符下执行

FLUSH PRIVILEGES;

记得后面要有分号’;’

虚拟主机的用户如果总是出现这个问题可找空间商协商解决。

十九、Too many connections (1040)链接过多

翻译:达到更大连接数

问题分析:

连接数超过了mysql设置的值,与max_connections 和wait_timeout 都有关系。wait_timeout的值越大,连接的空闲等待就越长,这样就会造成当前连接数越大

解决方法:

1.虚拟主机用户请联系空间商优化 MySQL 服务器的配置;

2.独立主机用户请联系服务器管理员优化 MySQL 服务器的配置,可参考:

修改 MySQL 配置文件 my.ini 或者 my.cnf 中的参数:

max_connections= 1000

wait_timeout = 10

修改后重启 MySQL ,如果经常性的报此错误,请做一下服务器的整体优化。

二十、There is no such grant defined for user ‘%s’ on host ‘%s’

错误编号:1141

问题分析:

MySQL 当前用户无权访问数据库。

解决方法:

1、虚拟主机用户请联系空间商,确认给你提供的帐号是否有授权数据库的权限。

2、独立主机用户请联系服务器管理员,确认给您提供的数据库帐号是否有管理此数据库的权限。

二十一、Error on rename of ‘%s’ to ‘%s’ (errno: %d)

error.:1025

问题分析:

请检查一下您的程序是否有修改数据库表名的语句。

解决方法:

1.请检查您的程序中哪些地方需要修改数据库表名;

2.如果您的实际应用确实需要修改到数据库表名的话,请联系空间商或者服务器管理员给您开放修改库名的权限和服务器本身是否正常。

二十二、Error reading file ‘%s’ (errno: %d)

error.:1023

问题分析:

数据库文件不能被读取。

解决方法:

1.虚拟主机用户请联系空间商查看数据库是否完好。

2.独立主机用户请联系服务器管理员检查一下 MySQL 本身是否正常, MySQL 是否可以读取文件,Linux 用户可以检查一下 MySQL 的数据库文件的属主是否正确以及本身的文件是否损坏。

二十三、Host ‘*****’ is blocked because of many connection errors; unblock with ‘mysqladmin flush-hosts’

error.:1129

问题分析:

数据库出现异常,请重启数据库。

解决方法:

1. 由于存在很多连接错误,主机’****’被屏蔽,虚拟主机用户请联系空间商处理,独立主机用户请联系服务器管理员,在 MySQL 的命令控制台下执行’mysqladmin flush-hosts’解除屏蔽即可,或者重启 MySQL 数据库

二十四、dropping database (can’t delete ‘%s’, errno: %d)

error.:1009

问题分析:

不能删除数据库文件,导致删除数据库失败。

解决方法:

1.检查您使用的数据库管理帐号是否有权限删除数据。

2.检查数据库是否存在。

二十五、Got error 28 from table handler

error.:1030

问题分析:

数据库所在磁盘空间已满。

解决方法:

1.虚拟主机用户请联系空间商增加 MySQL 所在的磁盘空间或者清理一些无用文件;

2.独立主机用户请联系服务器管理员增加 MySQL 所在的磁盘空间或者清理一些无用文件

二十六、Can’t create a new thread; if you are not out of available memory, you can consult the manual for a possible OS-dependent bug。

error.:11/35

问题分析:

数据库服务器问题,数据库操作无法创建新线程。一般是两个原因:

1.服务器系统内存溢出。

2.环境软件损坏或系统损坏。

解决方法:

1.虚拟主机用户请联系下空间商数据库服务器的内存和系统是否正常。

2.独立主机用户请联系服务器管理员检查服务器的内存和系统是否正常,如果服务器内存紧张,请检查一下哪些进程消耗了服务器的内存,同时考虑是否增加服务器的内存来提高整个的负载能力。

二十七、Error: Client does not support authentication protocol requested by server; consider upgrading MySQL client

error.:1251

问题分析:

如果你升级 MySQL 到 4.1 以上版本后遇到以上问题,请先确定你的 MySQL Client 是 4.1 或者更高版本( Windows 下有问题你就直接跳到下面看解决方法了,因为 MySQL 在 Windows 是 client 和 server 一起装上了的)。

解决方法:

1. Windows 平台

主要是改变连接 MySQL 的帐户的加密方式,MySQL 4.1/5.0 是通过 PASSWORD 这种方式加密的。可以通过以下两种方法得到解决:

1) mysql->SET PASSWORD FOR ‘some_user’@’some_host’=OLD_PASSWORD(‘new_password’);

2) mysql->UPDATE mysql.user SET Password=OLD_PASSWORD(‘new_password’) WHERE Host=’some_host’ AND User=’some_user’;

2. Linux/Unix 平台

Linux 平台下首先确定是否安装过 MySQL 的客户端,这个用 rpm 安装很简单,Linux 代码为:

rpm -ivh MySQL-client-4.1.15-0.i386.rpm

然后在编译 php 的时候要加上:

–with-mysql=/your/path/to/mysql

一般情况下都可以解决。如果还出现这种错误,可以按照下面的方法来做:

mysql->SET PASSWORD FOR ‘some_user’@’some_host’=OLD_PASSWORD(‘new_password’);

mysql->UPDATE mysql.user SET Password=OLD_PASSWORD(‘new_password’) WHERE Host=’some_host’ AND User=’some_user’;

二十八、Error: Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock’

error.:2023

问题分析:

出现这个错误一般情况下是因为下面两个原因:

1.MySQL 服务器没有开启。

2.MySQL 服务器开启了,但不能找到 socket 文件。

解决方法:

1.虚拟主机用户,请联系空间商确认数据库是否正常启动。

2.独立主机用户,请检查一下 MySQL 服务是否已经开启,没有开启,请启动 MySQL 服务;如果已经开启,并且是 Linux 系统,请检查一下 MySQL 的 socket 的路径,然后打开 config.inc.php 找到

$dbhost = ‘localhost’; 在 hostname 后面加冒号‘:’和 MySQL 的 socket 的路径。

比如 MySQL 服务器为 localhost

MySQL 的 socket 的路径为 /tmp/mysql.sock

那么就改成如下:

$dbhost = ‘localhost:/temp/mysql.sock’;

二十九、Can’t connect to MySQL server on ‘localhost’

error.:2023

问题分析:

MySQL 服务没有启动,一般是在异常的情况下 MySQL 无法启动导致的,比如无可用的磁盘空间,my.ini 里 MySQL 的 basedir 路径设置错误等。

解决方法:

1.检查磁盘空间是否还有剩余可用空间,尽量保持有足够的磁盘空间可用。

2.检查 my.ini 里的 basedir 等参数设置是否正确,然后重新启动下 MySQL 服务。

三十、Lost connection to MySQL server during query

error.:2023

问题分析:

数据库查询过程中丢失了与 MySQL 服务器的连接。

解决方法:

1.请确认您的程序中是否有效率很低的程序,比如某些插件,可以卸载掉插件,检查一下服务器是否正常;

2.服务器本身资源紧张,虚拟主机用户请联系空间商确认,独立主机用户请联系服务器管理员,检查一下服务器是否正常。

三十一、Got a packet bigger than \’max_allowed_packet\’ bytes

错误编号:1153

问题分析:调整了 Mantis 的上传附件的大小却没有调整 MySQL 的配置文件。

解决办法:

1、独立主机用户请按照以下方法调整:

查找 MySQL 的配置文件(my.cnf 或者 my.ini)

在 部分添加一句(如果存在,调整其值就可以):

max_allowed_packet=10M

重启 MySQL 服务就可以了。这里设置的是 10MB。

MySQL性能调优 – 你必须了解的15个重要变量

前言:

MYSQL 应该是更流行了 WEB 后端数据库。虽然 NOSQL 最近越来越多的被提到,但是相信大部分架构师还是会选择 MYSQL 来做数据存储。本文作者总结梳理MySQL性能调优的15个重要变量,又不足需要补充的还望大佬指出。

1.DEFAULT_STORAGE_ENGINE

如果你已经在用MySQL 5.6或者5.7,并且你的数据表都是InnoDB,那么表示你已经设置好了。如果没有,确保把你的表转换为InnoDB并且设置default_storage_engine为InnoDB。

为什么?简而言之,因为InnoDB是MySQL(包括Percona Server和MariaDB)更好的存储引擎 – 它支持事务,高并发,有着非常好的性能表现(当配置正确时)。这里有详细的版本介绍为什么

2.INNODB_BUFFER_POOL_SIZE

这个是InnoDB最重要变量。实际上,如果你的主要存储引擎是InnoDB,那么对于你,这个变量对于MySQL是最重要的。

基本上,innodb_buffer_pool_size指定了MySQL应该分配给InnoDB缓冲池多少内存,InnoDB缓冲池用来存储缓存的数据,二级索引,脏数据(已经被更改但没有刷新到硬盘的数据)以及各种内部结构如自适应哈希索引。

根据经验,在一个独立的MySQL服务器应该分配给MySQL整个机器总内存的80%。如果你的MySQL运行在一个共享服务器,或者你想知道InnoDB缓冲池大小是否正确设置,详细请看这里。

3.INNODB_LOG_FILE_SIZE

InnoDB重做日志文件的设置在MySQL社区也叫做事务日志。直到MySQL 5.6.8事务日志默认值innodb_log_file_size=5M是唯一更大的InnoDB性能杀手。从MySQL 5.6.8开始,默认值提升到48M,但对于许多稍繁忙的系统,还远远要低。

根据经验,你应该设置的日志大小能在你服务器繁忙时能存储1-2小时的写入量。如果不想这么麻烦,那么设置1-2G的大小会让你的性能有一个不错的表现。这个变量也相当重要,更详细的介绍请看这里。

当然,如果你有大量的大事务更改,那么,更改比默认innodb日志缓冲大小更大的值会对你的性能有一定的提高,但是你使用的是autocommit,或者你的事务更改小于几k,那还是保持默认的值吧。

4.INNODB_FLUSH_LOG_AT_TRX_COMMIT

默认下,innodb_flush_log_at_trx_commit设置为1表示InnoDB在每次事务提交后立即刷新同步数据到硬盘。如果你使用autocommit,那么你的每一个INSERT, UPDATE或DELETE语句都是一个事务提交。

同步是一个昂贵的操作(特别是当你没有写回缓存时),因为它涉及对硬盘的实际同步物理写入。所以如果可能,并不建议使用默认值。

两个可选的值是0和2:

* 0表示刷新到硬盘,但不同步(提交事务时没有实际的IO操作)

* 2表示不刷新岩困和不同步(也没有实际的IO操作)

所以你如果设置它为0或2,则同步操作每秒执行一次。所以明显的缺点是你可能会丢失上一秒的提交数据。具体来说,你的事务已经提交了,但服务器马上断电了侍枣前,那么你的提交相当于没有发生过。

显示的,对于金融机构,如银行,这是无法忍受的。不过对于大多数网站,可以设置为innodb_flush_log_at_trx_commit=0|2,即使服务器最终崩溃也没有什么大问题。毕竟,仅仅在几年前有许多网站还是用MyISAM,当崩溃时会丢失30s的数据(更不要提那令人抓狂的慢修复进程)。

那么,0和2之间的实际区别是什么?性能明显的差异是可以忽略不计,因为刷新到操作系统缓存的操作是非常快的。所以很明显应该设置为0,老清万一MySQL崩溃(不是整个机器),你不会丢失任何数据,因为数据已经在OS缓存,最终还是会同步到硬盘的。

5.SYNC_BINLOG

已经有大量的文档写到sync_binlog,以及它和innodb_flush_log_at_trx_commit的关系,下面我们来简单的介绍下:

a) 如果你的服务器没有设置从服务器,而且你不做备份,那么设置sync_binlog=0将对性能有好处。

b) 如果你有从服务器并且做备份,但你不介意当主服务器崩溃时在二进制日志丢失一些事件,那么为了更好的性能还是设置为sync_binlog=0.

c) 如果你有从服务器并且备份,你非常在意从服务器的一致性,以及能及时恢复到一个时间点(通过使用最新的一致性备份和二进制日志将数据库恢复到特定时间点的能力),那么你应该设置innodb_flush_log_at_trx_commit=1,并且需要认真考虑使用sync_binlog=1。

问题是sync_binlog=1代价比较高 – 现在每个事务也要同步一次到硬盘。你可能会想为什么不把两次同步合并成一次,想法正确 – 新版本的MySQL(5.6和5.7,MariaDB和Percona Server)已经能合并提交,那么在这种情况下sync_binlog=1的操作也不是这么昂贵了,但在旧的mysql版本中仍然会对性能有很大影响。

6.INNODB_FLUSH_METHOD

将innodb_flush_method设置为O_DIRECT以避免双重缓冲.唯一一种情况你不应该使用O_DIRECT是当你操作系统不支持时。但如果你运行的是Linux,使用O_DIRECT来激活直接IO。

不用直接IO,双重缓冲将会发生,因为所有的数据库更改首先会写入到OS缓存然后才同步到硬盘 – 所以InnoDB缓冲池和OS缓存会同时持有一份相同的数据。特别是如果你的缓冲池限制为总内存的50%,那意味着在写密集的环境中你可能会浪费高达50%的内存。如果没有限制为50%,服务器可能由于OS缓存的高压力会使用到swap。

简单地说,设置为innodb_flush_method=O_DIRECT。

7.INNODB_BUFFER_POOL_INSTANCES

MySQL 5.5引入了缓冲实例作为减小内部锁争用来提高MySQL吞吐量的手段。

在5.5版本这个对提升吞吐量帮助很小,然后在MySQL 5.6版本这个提升就非常大了,所以在MySQL5.5中你可能会保守地设置innodb_buffer_pool_instances=4,在MySQL 5.6和5.7中你可以设置为8-16个缓冲池实例。

你设置后观察会觉得性能提高不大,但在大多数高负载情况下,它应该会有不错的表现。

对了,不要指望这个设置能减少你单个查询的响应时间。这个是在高并发负载的服务器上才看得出区别。比如多个线程同时做许多事情。

8.INNODB_THREAD_CONCURRENCY

InnoDB有一种方法来控制并行执行的线程数 – 我们称为并发控制机制。大部分是由innodb_thread_concurrency值来控制的。如果设置为0,并发控制就关闭了,因此InnoDB会立即处理所有进来的请求(尽可能多的)。

在你有32CPU核心且只有4个请求时会没什么问题。不过想像下你只有4CPU核心和32个请求时 – 如果你让32个请求同时处理,你这个自找麻烦。因为这些32个请求只有4 CPU核心,显然地会比平常慢至少8倍(实际上是大于8倍),而然这些请求每个都有自己的外部和内部锁,这有很大可能堆积请求。

下面介绍如何更改这个变量,在mysql命令行提示符执行:

对于大多数工作负载和服务器,设置为8是一个好开端,然后你可以根据服务器达到了这个限制而资源使用率利用不足时逐渐增加。可以通过show engine innodb status\G来查看目前查询处理情况,查找类似如下行:

9.SKIP_NAME_RESOLVE

这一项不得不提及,因为仍然有很多人没有添加这一项。你应该添加skip_name_resolve来避免连接时DNS解析。

大多数情况下你更改这个会没有什么感觉,因为大多数情况下DNS服务器解析会非常快。不过当DNS服务器失败时,它会出现在你服务器上出现“unauthenticated connections” ,而就是为什么所有的请求都突然开始慢下来了。

所以不要等到这种事情发生才更改。现在添加这个变量并且避免基于主机名的授权。

10.INNODB_IO_CAPACITY, INNODB_IO_CAPACITY_MAX

* innodb_io_capacity:用来当刷新脏数据时,控制MySQL每秒执行的写IO量。

* innodb_io_capacity_max: 在压力下,控制当刷新脏数据时MySQL每秒执行的写IO量

首先,这与读取无关 – SELECT查询执行的操作。对于读操作,MySQL会尽更大可能处理并返回结果。至于写操作,MySQL在后台会循环刷新,在每一个循环会检查有多少数据需要刷新,并且不会用超过innodb_io_capacity指定的数来做刷新操作。这也包括更改缓冲区合并(在它们刷新到磁盘之前,更改缓冲区是辅助脏页存储的关键)。

第二,我需要解释一下什么叫“在压力下”,MySQL中称为”紧急情况”,是当MySQL在后台刷新时,它需要刷新一些数据为了让新的写操作进来。然后,MySQL会用到innodb_io_capacity_max。

那么,应该设置innodb_io_capacity和innodb_io_capacity_max为什么呢?

更好的方法是测量你的存储设置的随机写吞吐量,然后给innodb_io_capacity_max设置为你的设备能达到的更大IOPS。innodb_io_capacity就设置为它的50-75%,特别是你的系统主要是写操作时。

通常你可以预测你的系统的IOPS是多少。例如由8 15k硬盘组成的RAID10能做大约每秒1000随机写操作,所以你可以设置innodb_io_capacity=600和innodb_io_capacity_max=1000。许多廉价企业SSD可以做4,000-10,000 IOPS等。

这个值设置得不完美问题不大。但是,要注意默认的200和400会限制你的写吞吐量,因此你可能偶尔会捕捉到刷新进程。如果出现这种情况,可能是已经达到你硬盘的写IO吞吐量,或者这个值设置得太小限制了吞吐量。

11.INNODB_STATS_ON_METADATA

如果你跑的是MySQL 5.6或5.7,你不需要更改innodb_stats_on_metadata的默认值,因为它已经设置正确了。

不过在MySQL 5.5或5.1,强烈建议关闭这个变量 – 如果是开启,像命令show table status会立即查询INFORMATION_SCHEMA而不是等几秒再执行,这会使用到额外的IO操作。

从5.1.32版本开始,这个是动态变量,意味着你不需要重启MySQL服务器来关闭它。

12.INNODB_BUFFER_POOL_DUMP_AT_SHUTDOWN & INNODB_BUFFER_POOL_LOAD_AT_STARTUP

innodb_buffer_pool_dump_at_shutdown和innodb_buffer_pool_load_at_startup这两个变量与性能无关,不过如果你偶尔重启mysql服务器(如生效配置),那么就有关。当两个都激活时,MySQL缓冲池的内容(更具体地说,是缓存页)在停止MySQL时存储到一个文件。当你下次启动MySQL时,它会在后台启动一个线程来加载缓冲池的内容以提高预热速度到3-5倍。

两件事:

之一,它实际上没有在关闭时复制缓冲池内容到文件,仅仅是复制表空间ID和页面ID – 足够的信息来定位硬盘上的页面了。然后它就能以大量的顺序读非常快速的加载那些页面,而不是需要成千上万的小随机读。

第二,启动时是在后台加载内容,因为MySQL不需要等到缓冲池内容加载完成再开始接受请求(所以看起来不会有什么影响)。

从MySQL 5.7.7开始,默认只有25%的缓冲池页面在mysql关闭时存储到文件,但是你可以控制这个值 – 使用innodb_buffer_pool_dump_pct,建议75-100。

这个特性从MySQL 5.6才开始支持。

13.INNODB_ADAPTIVE_HASH_INDEX_PARTS

如果你运行着一个大量SELECT查询的MySQL服务器(并且已经尽可能优化),那么自适应哈希索引将下你的下一个瓶颈。自适应哈希索引是InnoDB内部维护的动态索引,可以提高最常用的查询模式的性能。这个特性可以重启服务器关闭,不过默认下在mysql的所有版本开启。

这个技术非常复杂,在大多数情况下它会对大多数类型的查询直到加速的作用。不过,当你有太多的查询往数据库,在某一个点上它会花过多的时间等待AHI锁和闩锁。

如果你的是MySQL 5.7,没有这个问题 – innodb_adaptive_hash_index_parts默认设置为8,所以自适应哈希索引被切割为8个分区,因为不存在全局互斥。

不过在mysql 5.7前的版本,没有AHI分区数量的控制。换句话说,有一个全局互斥锁来保护AHI,可能导致你的select查询经常撞墙。

所以如果你运行的是5.1或5.6,并且有大量的select查询,最简单的方案就是切换成同一版本的Percona Server来激活AHI分区。

14.QUERY_CACHE_TYPE

如果人认为查询缓存效果很好,肯定应该使用它。好吧,有时候是有用的。不过这个只在你在低负载时有用,特别是在低负载下大多数是读取,小量写或者没有。

如果是那样的情况,设置query_cache_type=ON和query_cache_size=256M就好了。不过记住不能把256M设置更高的值了,否则会由于查询缓存失效时,导致引起严重的服务器停顿。

如果你的MySQL服务器高负载动作,建议设置query_cache_size=0和query_cache_type=OFF,并重启服务器生效。那样Mysql就会停止在所有的查询使用查询缓存互斥锁。

15.TABLE_OPEN_CACHE_INSTANCES

从MySQL 5.6.6开始,表缓存能分割到多个分区。

表缓存用来存放目前已打开表的列表,当每一个表打开或关闭互斥体就被锁定 – 即使这是一个隐式临时表。使用多个分区绝对减少了潜在的争用。

从MySQL 5.7.8开始,table_open_cache_instances=16是默认的配置。

欢迎做Java的工程师朋友们私信我资料免费获取免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)

其中覆盖了互联网的方方面面,期间碰到各种产品各种场景下的各种问题,很值得大家借鉴和学习,扩展自己的技术广度和知识面。

关于mysql查询导致服务器崩溃的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 服务器崩溃!原因竟是mysql查询? (mysql查询导致服务器崩溃)