2019-06-20 更新:
如果你尝试了以下的方式依然解决不了你的问题,老四又邪门歪道的搞了一个终极杀招,那就是写一个 shell 脚本监控这个 mysql.sock 文件,当文件被莫名其妙的被删除时,脚本及时监控然后重启 MySQL。
脚本代码如下:
1 2 3 4 5 6 7 8 |
#!/bin/bash while true do myFile="mysql.sock的文件路径" if [ ! -e "$myFile" ]; then systemctl restart mysql fi done |
保存为 mysql.sh,设置用户、用户组为 root 即可。大家可以试一下。
—————-丑逼分割线—————-
想必搞 MySQL 的,在服务器上搞过 MySQL 的同仁都遇到过这个类似于「Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock'(2);」(路径也有可能是「Can’t connect to local MySQL server through socket ‘/temp/mysql.sock'(2);」)令人脑瓜子嗡嗡的问题。你可能查了百度无数遍,各路大神都特么不知道都在瞎哔哔一些什么乱码七糟的,什么硬盘满了,什么 my.cnf 里面的 sock 文件路径配置的不正确了,还有诸如重启就好了、修改乱七八糟这个那个文件的权限这种完全 XX (你懂的)这类的办法。
甚至你也谷歌了,但是依然治标不治本,老四也被这个问题折磨了半年多了,之前懒得管他,每次遇到这个问题直接重启服务器就好了,但是现在不行了,我发现这破玩意现在越来越猖獗了,索性研究了一下,弄出点稍微有效长久的解决办法,本着分享交流的精神,与诸君共享,由于老四也不是什么大神,解决方式并不一定最好的,但是思路最起码是正确的。废话说完,开始。
一、基本知识回顾:
MySQL客户端连接方式:
我们无论通过什么样的客户端连接MySQL,其实都是与 MySQL 数据库实例进行通信的一个过程,所以通信方式有很多,包括但不限于以下这些:
- 管道
- 命名管道
- 命名字
- TCP/IP
- UNIX套接字
二、mysql.sock 文件丢失问题的根源
好,前方高能,请注意,问题来了。在 MySQL 服务器本机上我们连接数据库时,经常会出现 mysql.sock 不存在的现象,MySQL 会打印出上面提及到的「Can ‘t connect to local MySQL server through socket ‘/temp/mysql.sock'(2);」,我告诉你,无论你怎么折腾,你把这个 mysql.sock 文件设置在无论哪个目录下面都避免不了这个套接字文件会因为各种原因被删除。
注意:本次探讨的问题仅限于在 Linux 系统 MySQL 的环境问题处理,不包括 Windows,Windows 版本中的 MySQL 其实没有 UNIX 套接字这种通信的。
这是为啥呢,老四也不知道为啥,不知道这个套接字文件为什么总被删除,这是为啥呢,老四也不知道为啥,不知道这个套接字文件为什么总被删除。但是我们能知道的就是肯定 MySQL 数据库出毛病了,所以我们首先一定要找到 MySQL 崩溃是因为什么。首先我们在服务器中查看 MySQL 日志(仅限老四遇到的情况,实际情况你遇到的可能跟老四不一样,老四的 MySQL 使用 rpm 安装 5.6.40 版本):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
[Note] Plugin 'FEDERATED' is disabled. [Note] InnoDB: Using atomics to ref count buffer pool pages [Note] InnoDB: The InnoDB memory heap is disabled [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins [Note] InnoDB: Memory barrier is not used [Note] InnoDB: Compressed tables use zlib 1.2.3 [Note] InnoDB: Using Linux native AIO [Note] InnoDB: Using CPU crc32 instructions [Note] InnoDB: Initializing buffer pool, size = 128.0M [Note] InnoDB: Completed initialization of buffer pool [Note] InnoDB: Highest supported file format is Barracuda. [Note] InnoDB: The log sequence numbers 279621649 and 279621649 in ibdata files do not match the log sequence number 295687446 in the ib_logfiles! [Note] InnoDB: Database was not shutdown normally! [Note] InnoDB: Starting crash recovery. [Note] InnoDB: Reading tablespace information from the .ibd files... [Note] InnoDB: Restoring possible half-written data pages [Note] InnoDB: from the doublewrite buffer... [Note] InnoDB: 128 rollback segment(s) are active. [Note] InnoDB: Waiting for purge to start [Note] InnoDB: 5.6.40 started; log sequence number 295687446 [Note] Server hostname (bind-address): '*'; port: xxxx [Note] - '::' resolves to '::'; [Note] Server socket created on IP: '::'. [Note] Event Scheduler: Loaded 0 events [Note] mysqld: ready for connections. Version: '5.6.40' socket: '/var/lib/mysql/mysql.sock' port: xxxx MySQL Community Server (GPL) [Warning] IP address '' could not be resolved: Name or service not known |
日志不用我多说了,大致的意思就是 MySQL 的 InnoDB 存储引擎的缓存池需要 64MB 的内存,但是系统已经没有那么多了给不了,然后 MySQL 的防御机制就直接 crash 掉,这个 crash 并不是 MySQL 自身杀死自己,MySQL 还活着,但是就在这个防御过程中把 mysql.sock 给删掉了,删掉了他重新尝试创建这个mysql.sock 文件但是没能成功,然后就死死地在,那里无法提供服务,随之你的环境就宕机了。
所以,首先这个问题需要我们先手解决,除了你加大你服务器的内存之外,也可以将 MySQL 的 InnoDB 设置的小一些。/etc/my.cnf 文件里面有一个innodb_buffer_pool_size 属性配置,默认是注释掉的,老四的虚拟机上测试 1G 内存 innodb_buffer_pool_size 默认会占用 128M 的内存空间,所以为了防止崩溃你可以打开该注释项,改成 64M 甚至 32M,形如「innodb_buffer_pool_size = 64M」。
接下来再说为什么会有这个套接字文件的原因。mysql.sock 的生成就是因为我们指定了 localhost 作为了我们连接数据库的主机名,MySQL 一看你用的是localhost,他就默认使用 UNIX 套接字文件连接,这个文件就是这个 mysql.sock,就不会使用 TCP/IP 的连接方式了。
按理说,其实我们连接一台数据库服务器,是要跟数据库服务器通信的,一般都是通过 TCP/IP 连接的,包括企业级开发等。但是我们日常中也大量存在这种案例,项目和 MySQL 数据库在同一台机器上面,或是开发,或是站长上线的小网站,初期网站建设就为 MySQL 单独设置一台独立的服务器或者是直接上 MySQL 的云服务闲心大多数人也是不愿意牺牲这样的财力的,所以这样的一批人群就总会遇到这种问题。
三、找到根源,避免问题再次发生
前面我们已经找到原因了,但是我们找不到 mysql.sock 总会莫名其妙的被删除的原因,所以换个思路来解决问题–那就是在 MySQL 服务器本机上连接 MySQL 不使用 localhost 这种 UNIX 套接字的方式来访问数据库。怎么办呢?如果你的知识丰富,相信你是知道如果在项目中配置 MySQL 的服务器地址的时候不配置 localhost 而是配置 127.0.0.1 的话,后者是用 TCP/IP 的形式来访问 MySQL 数据库的。但是,可但是,多半我们这样做的时候其实问题还没有解决,你会发现他走的还是 UNIX 套接字。
这里我们需要简单的作进一步的处理,在 MySQL 数据库中的 mysql 库中有一张 user 表,这个 user 表的存储记录是有顺序的,所以当我们只是单纯的设置 HOST 为 127.0.0.1 的时候,MySQL 会默认读取到他是属于 localhost 本地连接,然后它就给你转换了,就再一次避开了 TCP/IP 连接,所以我们要改变数据库中 localhost 和 127.0.0.1 的位置,将 127.0.0.1 放在记录行的前面就好了。如下图:
我已经说的很清楚了,老四亲测这种方式对于项目来说很稳定,那个 mysql.sock 就让他爱咋咋地吧,再也不用因为它而烦心了。
多说一嘴,其实打开 MySQL 的 skip-name-resolve 属性也会达到同样的效果,这个属性要求链接 MySQL 必须使用域名或者 IP 地址,禁止你使用 localhost 做解析,然后他会做 DNS 反查,但是弊端就是当访问量上来的时候泛解析会影响性能,如果愿意使用这种方式可以直接在 my.cnf 中开启此属性即可。
最后附赠一条 sql(在 Linux 下使用 TCP/IP 协议链接 MySQL 客户端):
1 |
mysql --protocol=TCP -u root -p -h localhost |
这样写,即使你使用 localhost 他也是用 TCP 进行通信,不信的你可以在自己的 Linux 服务器中把 mysql.sock 删除试一下,照样连接成功!
问题解决了,十分开心,故做此记录,望各位大佬不吝批评指导,共同交流。
更博不易,如果觉得文章对你有帮助并且有能力的老铁烦请赞助盒烟钱,点我去赞助。或者扫描文章下面的微信/支付宝二维码打赏任意金额,老四这里抱拳了。赞助时请备注姓名或者昵称,因为您的署名会出现在赞赏列表页面,您的赞赏钱财也会被用于小站的服务器运维上面,再次抱拳。