# sdb报告-10 错误问题定位
在sdb 的集群环境中,如果面对的是一个高并发的操作场景,有时候会莫名其妙地报告 -10 错误。

在 sdb 的错误列表中,-10 错误代表:系统错误。

这是一个笼统的错误描述,也是一个让人迷惑的错误描述。"系统错误"?什么鬼的系统错误,究竟是什么地方导致了系统错误?

作者通过分析大量的 -10 错误案例,发现大部分情况下,都是由于线程创建失败。

一般抛出 -10 错误的都是数据节点,并且一般数据节点的 diaglog 日志关键的错误信息如下

```
Failed to create new agent: boost::thread_resource_error: Resource temporaily unavailable
Failed to create new agent, probe = 30
Failed to create subagent thread, rc = -10
Failed to start session EDU, rc = -10
```

# linux 线程创建失败,原因分析

一般操作linux 系统在创建线程时,会受限于哪些参数呢,主要有两个

* 文件句柄数限制
* 内存资源

## 系统句柄

我们先来介绍文件句柄数
在linux 操作系统中,号称一切皆为文件,无论是进程、线程、socket 还是其他,最终都会被操作系统归为文件操作。操作系统或者进程,每申请一个资源,例如线程、socket,都会打开一个文件,那么这个文件打开状态,就可以简单理解为文件句柄。

那么句柄数限制又是什么呢?其实就是操作系统,或者某个进程所能够打开的最多文件的数量的限制。

大家有了这个概念后,我们再来看操作系统是如何对文件句柄数进行限制的。

在操作系统中,有一个神奇的命令 -- ulimit ,专门设置这些奇奇怪怪的限制值,进程最大文件句柄数和用户最大进程数就是其中的设置。

### 进程最大文件句柄数

例如我们可以查看 root 用户的 ulimit 输出, -n open file = 1024 就是root 用户允许一个进程打开的最大文件句柄数。

这里有一个小细节需要大家注意的。

由于root 用户是linux 中的管理员用户,所以如果root 用户的 ulimit open file 设置成 1024, 那么其他的用户,例如:test、mysql 用户等,想将 ulimit opon file 设置成 大于 1024,是不允许的。

这个大家一定要知道,如果希望将普通用户的 ulimit 值修改得很大,一定要先修改 root 用户的值。

### 用户最大进程数
一个系统用户,也有它最大的进程数,参数为 ulimit -u 命令。

该参数的官方解释如下:

```
Linux itself has a Max Processes per user limit. This feature allows us to control the number of processes an existing user on the server may be authorized to have
```

虽然解释是一个用户的进程限制,但是从使用效果分析,对线程数也有明显限制效果,毕竟线程是从进程中派生出来的资源。

一个用户的进程数限制,修改的方式和 ulimit -n 的方式一样。

### 系统总句柄限制

另外,关于句柄数的限制,还不单单是进程中和一个用户的句柄数限制,还有整个操作系统的句柄数限制,因为一个操作系统,总不能无限地打开句柄的。所以又引入另外一个设置,操作系统最大打开的句柄数限制。

以 centos 7 系统为例,该参数是被保存在 /proc/sys/fs/file-max 文件中

如果操作系统总的句柄数已经达到上限,那么即使进程还没有启动几个线程,也会出现句柄不够的情况。

如果希望临时修改操作系统最大句柄数的设置,可以直接执行

```
echo 2000000 > /proc/sys/fs/file-max
```

如果希望永久修改操作系统最大句柄数的设置,可以编辑 /etc/sysctl.conf 文件,增加 fs.file-max = 2000000 内容,然后在root 用户中执行

```
sysctl -p
```

## 系统内存

我们接着来介绍内存资源
因为在创建线程时,在linux 中,是需要给它预先分配内存的 – 也叫栈大小,用来存储线程中数据的值。

这里再科普另外一个知识,一个程序中,内存主要分为两个大的部分,一个称为 “堆”,一个称为“栈”。“堆”是程序用来保存常量和变量名字的,“栈”则是程序来用保存具体的变量数字的。

好,背景知识介绍完毕后,开始进入正题。

### 线程栈大小影响

开始时说到,如果系统内存资源不足,也是无法创建线程的。这个原因就是在于创建线程时,操作系统需要分配一块内存给线程,这个内存是多大呢,就是 ulimit 中 -s stack size 的大小。如果操作系统连 stack size 大小的内存都无法 malloc 了,创建线程就会失败。

有一些读者可能会奇怪,为啥这么一点内存都没有了?

其实如果仔细查看操作系统,你就会发现,那么多进程,每个进程又是那么多线程在运行,每个线程都在申请内存(注意,这块的内存是虚拟内存),内存不足正常的很。这个也容易让人联想到JVM 的OOM ,但是他们真的不是一回事,大家千万不要误会。

要解决这个问题也比较简单 –- 简单粗暴?就是将 ulimit 中 -s stack size 调小一点,每个线程不要申请那么多内存了,操作系统的内存资源就会更加的充裕。毕竟进程、线程这些,都是用完就完了,不可能都永久占用内存的。

在centos 7 的系统中,默认的 stack size 是8MB,一般使用默认值,都不会出现 "创建线程" 的错误,只有当极限情况才会对用户造成影响。

### 内存地址检查

在linux 系统中,内存管理是一个细致活。

其实在linux 的系统内存管理中,有两层

* 物理内存
* 虚拟内存

物理内存很好理解,就是用户为操作系统配置的RAM 大小,也是人们日常所说的服务器内存大小。

虚拟内存,是操作系统为了更好管理物理内存而设计出来的一层虚拟资源。因为操作系统在运行过程中,很多进程都在使用、释放内存,真实 free 的物理内存必然是不连续的。

所以操作系统为了让程序在使用内存时,更加方便的使用物理内存,构造了一层虚拟内存。

进程在向操作系统 malloc 一段连续的内存时,实际从虚拟内存中申请了一段连续的地址。在操作系统的内存映射表中,记录了虚拟内存地址指向真实的物理内存地址。

同时,即使程序 malloc 了内存,但实际上在 malloc 后,并不会真的立马占用了物理内存,只有当真正开始保存数据时,才会实际使用物理内存。

介绍到这里,读者们可能就对内存 malloc 有所了解了。

提问:如果操作系统真的是没有内存了而导致无法创建新的线程,那么如何定位这个问题呢?

在linux 操作系统中,实际上时刻都在记录内存的使用情况。

用户可以通过以下命令获得重要信息

```
cat /proc/meminfo | grep Commit
```

该命令将打印两个重要的数值
* CommitLimit
* Committed_AS

CommitLimit 参数,是操作系统最大可以 malloc 的内存的大小。

Committed_AS 参数,是操作系统当前已经被 malloc 了的内存的大小。

所以简单的总结,就是当 Committed_AS 参数的值无限接近 CommitLimit 参数的值时,证明当前的操作系统,真的没有太多可用内存可以继续给 malloc 了。

### 内核参数中的内存管理
针对linux 系统的内存控制,实际上真的是一个细致活。

它对内存的管理,各种参数有着交叉互相影响关系,作者在这里尝试使用毕生功力,尽量为读者解释明白。读者如果还有疑问,请咨询谷姐和度娘,作者本人可能会对大家热情的提问,累觉不爱

sdb报告-10 错误问题定位的更多相关文章

  1. mysql-5.7.10-winx64 MySQL服务无法启动,服务没有报告任何错误的解决办法

      总结报错原因:在my.init文件下新增data目录(datadir = F:\mysqldata ) 最新解压版本的mysql 解压安装的时候报错D:\mysql\mysql-5.7.10-wi ...

  2. mysql 5.7 非正常安装,无法启动 服务没有报告任何错误

    以前,完整安装mysql5.7程序时,由于程序太大,可以将安装缓存目录中的安装文件(较小)复制出来后,留以后使用. mysql--win32.msi 2 mysql-5.7.17-winx64.msi ...

  3. mysql-5.7.9-winx64 MySQL服务无法启动,服务没有报告任何错误的解决办法

    问题背景 最新解压版本的mysql 解压安装的时候报错 D:\mysql-5.7.9-winx64\bin>net start mysql MySQL 服务正在启动 . MySQL 服务无法启动 ...

  4. SVN中与资源库同步时报告了错误。1 中的 0 个资源已经同步

    SVN中与资源库同步时报告了错误.1 中的 0 个资源已经同步 原因: 文件被lock, 此时再次提交则出错,解决办法就是clean释放锁即可再次提交: 解决方案: 右键项目–>team–> ...

  5. Alpha 冲刺报告(10/10)

    Alpha 冲刺报告(10/10) 队名:洛基小队 峻雄(组长) 已完成:阿尔法版的ppt 明日计划:总结阿尔法版的问题 剩余任务:角色属性脚本的完整版本 困难:缺乏编码经验,编码进度比较慢 ---- ...

  6. Illegal instruction错误的定位---忽略编译期警告的代价

    在原计算机的linux c++程序可以正确跑起来,但是换了一台机器运行时出现致命错误,程序直接当掉,错误提示如下: Illegal instruction (core dumped) 造成改错的主要原 ...

  7. 【mysql】【windows】MySQL 服务无法启动,服务没有报告任何错误,请键入 NET HELPMSG 3534 以获得更多的帮助。

    成功安装以后,启动MySQL,输入: net start mysql 提示: ”MySQL 服务无法启动,服务没有报告任何错误,请键入 NET HELPMSG 3534 以获得更多的帮助.” 查了下, ...

  8. windows的mysql无法启动 服务没有报告任何错误

    相信很多人都遇到过安装Mysql的时候出现各种各样的问题,今天小编就教大家解决window下mysql服务没有报告任何错误的情况下无法启动 的问题.本文所用的mysql版本是5.7以上版本,解决方法: ...

  9. mysql5.7安装中的问题(服务无法启动。服务没有报告任何错误。排查方法)

    1.拒绝访问的问题 权限不够,必须以管理员身份启动命令行 2.MySQL 服务无法启动.服务没有报告任何错误. 进入到你的mysql安装目录,C:\Program Files\MySQL\MySQL ...

随机推荐

  1. hihoCoder 1014 : Trie树(字典树)

    传送门 Description 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一本词典,于是小Hi就向小 ...

  2. jQury+Ajax与C#后台交换数据

    -------------------------------------------jQury+Ajax调用后台方法----------------------------------------- ...

  3. Spring学习(四)--面向切面的Spring

    一.Spring--面向切面 在软件开发中,散布于应用中多处的功能被称为横切关注点(cross- cutting concern).通常来讲,这些横切关注点从概念上是与应用的业 务逻辑相分离的(但是往 ...

  4. MySQL-第四篇索引

    1.创建索引的作用 创建索引的唯一作用就是加速对表的查询.索引通过使用快速路径访问方法来快速定位数据,从而减少了磁盘的I/O. 2.索引和表一样也是数据库中的一种对象,但它必须从属于某张表,不能独立存 ...

  5. 【题解】Sigitseeing Tour

    题目大意 有一张$n$个结点,$m$条混合边的图($1 \leq n \leq 200$,$1 \leq m \leq 1000$),求这张图是否存在欧拉回路. 题解 因为有混合边,所以我们要先给无向 ...

  6. proxool连接池配置方法

    proxool.properties: jdbc-1.proxool.alias=test #jdbc-1.proxool.driver-class=com.mysql.jdbc.Driver #jd ...

  7. 2018CCPC吉林赛区(重现赛)

    http://acm.hdu.edu.cn/contests/contest_show.php?cid=867 A题,直接分块,不知道正解是什么. #include<bits/stdc++.h& ...

  8. c# 添加数据

    /// <summary> /// 新增一条省份记录 /// </summary> /// <param name="model"></p ...

  9. .bat 文件调用python脚本

    1.将clearlog.py 脚本放在指定目录 比如 我放在 C:\Users\Administrator\Desktop 上 也就是桌面上 2.创建一个.bat 位后缀名的脚本 3.写入如下脚本 @ ...

  10. 从1<2<3的语法糖说起

    python有一个很有意思的语法糖你可以直接写1<2<3. 这复合我们通常意义上的数学不等式,但对学过C等语言其实是有疑惑的. 我们知道不等式返回的其实是个Bool值,在C中是1,0因此C ...