Wishlist 0 ¥0.00

MySQL Innodb 并发涉及参数

1 参数作用

    MySQL的各个插件式引擎中,都会对事务及线程做一定的处理和优化。在Innodb引擎中,总是尝试保持 innodb内 操作系统的线程数(暂命名为innodb_thread) 应该小于或等于 系统可提供给innodb处理事务的线程数(暂命名为system_innodb_thread)。在大多数情况下,innodb_thread都不会指定一个限制值,而是让它想要多少直接申请多少。

    当 innodb_thread 大于system_innodb_thread 时,持续时间较长时,会导致服务器的线程资源被数据库使用,CPU可能居高不下,甚至引发宕机。

    这个时候,Innodb内部可以提供一个参数来限制 并发线程(同一时刻可处理的请求数),当并发数达到 并发线程限制数时,再接收到一个新的请求,那么这个请求需要在下次请求前先sleep一段时间,如果sleep后再请求还是没有多余线程提供其执行,那么,它就会进入到先进先出的队列中等待执行。这里注意下,等待线程,不计入 innodb_thread 。innodb_thread_concurrency 参数因此而来。

   可以通过innodb_thread_concurrency 来调节  并发线程数的限制值,使用innodb_thread_sleep_delay来调整当 并发 thread 到达 innodb_thread_concurrency时需要sleep的时间。当请求被innodb接受的时候,会获得一个 消费凭证 innodb_concurrency_tickets (默认5000次),当这个请求中有多个SQL被执行的时候,每执行一次,消费一次tickets,在次数用完之前,该线程重新请求时无须再进行前面 thread 是否达到 并发限制值的检查。

   同时 innodb_commit_concurrency也控制了多线程并发提交的数量。如果 innodb_thread_concurrency  设置的有点大innodb_commit_concurrency应该做出相应的调整,否则会造成大量线程阻塞。

   所以,跟并发相关的有这几个参数设置:innodb_thread_concurrency、innodb_thread_sleep_delay、innodb_concurrency_tickets、innodb_commit_concurrency

跟innodb_thread_concurrency相似的参数有 thread_concurrency ,但是它在5.6版本的官方文档中已被标识为过时,在5.7.2版本废除了该参数,所以我们这里不涉及对该参数的测试及描述。

2 参数设置

2.1 innodb_thread_concurrency

2.1.1 默认值

   innodb_thread_concurrency默认是0,则表示没有并发线程数限制,所有请求都会直接请求线程执行。注意:当 innodb_thread_concurrency 设置为0时,则innodb_thread_sleep_delay的设置将会被忽略,不起作用。如果数据库没出现性能问题时,使用默认值即可。

2.1.2 大于0

   当innodb_thread_concurrency>0,则表示有 并发数限制,当一个新的请求发起时,会检查当前并发线程数是否达到了 innodb_thread_concurrency的限制值,如果有,则需要sleep一段时间(sleep的设置详见下一部分),然后再再次请求,如果再次请求时,当前并发数还是达到限制值,那么就会进入FIFO队列等待执行。当进入到内核执行时,会得到一个 消费凭证 ticket,则这个线程,在后面的多次进入innodb执行操作是都不需要重复上面的检查步骤,当把次数消费完,那么这个线程就会被驱逐,等待下次再次进入Innodb,再重新分配ticket。

2.1.3 建议配置(来自官网)

  • 当并发用户线程数量小于64,建议设置innodb_thread_concurrency=0;
  • 如果负载不稳定,时而低,时而高到峰值,建议先设置innodb_thread_concurrency=128,并通过不断的降低这个参数,96, 80, 64等等,直到发现能够提供最佳性能的线程数,例如,假设系统通常有40到50个用户,但定期的数量增加至60,70,甚至200。你会发现,性能在80个并发用户设置时表现稳定,如果高于这个数,性能反而下降。在这种情况下,建议设置innodb_thread_concurrency参数为80,以避免影响性能;
  • 如果DB服务器上还允许其他应用,需要限制mysql的线程使用情况,则可以设置可分配给DB的线程数,但是不建议DB上跑其他应用,也不建议这么设置,因为这样可能导致数据库没有对硬件最优使用;
  • 设置过高值,可能会因为系统资源内部争夺导致性能下降;
  • 在大多数情况下,最佳的值是小于并接近虚拟CPU的个数;
  • 定期监控和分析DB,因为随着数据库负载的变化,业务的增加,innodb_thread_concurrency也需要动态的调整。

2.2 innodb_thread_sleep_delay

   5.6.3版本前,需要反复测试才能确定innodb_thread_sleep_delay值,并且固定为一个值,在5.6.3版本后,因为 Innodb 自动调整innodb_thread_sleep_delay参数:

  • Innodb_adaptive_max_sleep_delay:最大sleep的时间,微秒为单位

可以通过设置参数 innodb_adaptive_max_sleep_delay 来限制 innodb_thread_sleep_delay的最大值,不设置 innodb_thread_sleep_delay的取值情况,让Innodb自动跟进负载来调整,当系统负荷较高时,Innodb动态调整slee时间可使得数据库稳定运行。

2.3 innodb_commit_concurrency

   该值只能为默认值0,mysql不限制并发提交。大于0表示允许N个事务在同一时间点提交,N的范围是0-1000。 

    注意事项:mysqld运行时,不许把innodb_commit_concurrency 的值从0改为非0,或非0的值改为0;但允许从N改为M(N及M均大于0)

2.4 innodb_concurrency_tickets

   默认是5000(基于5.6,5.7)。

   如果innodb_concurrency_tickets设置小些,适用于小事物操作较多的系统,可以快速使用完线程后退出来,提供给其他请求使用;而对于大事务来说,可能会循环进入等待队列中等待执行完成,这会耗费更多时间及资源;如果innodb_concurrency_tickets设置大些,适用于大事务频繁操作的系统,这样大事务则不需要频繁进入queue等待队列,可以通过较少的请求来处理;但是对于小事务来说,则意味着他们要等待更长的时候,才能排队进入到内核执行。所以,当innodb_thread_concurrency>0时,需要上下调整 innodb_concurrency_tickets ,使其达到最佳性能。可以通过show engine innodb status 的queue查看,也可以通过INFORMATION_SCHEMA.INNODB_TRXTRX_CONCURRENCY_TICKETS查看消费次数情况。

调整 MySQL 并发相关的参数

MySQL server 是多线程结构,包括后台线程和客户服务线程。多线程可以有效利用服务器资源,提高数据库的并发性能。在 MySQL 中,控制并发连接和线程的主要参数包括 max_connections、back_log、thread_cache_size 以及 table_open_cache 等。

一、调整 max_connections,提高并发连接

参数 max_connections 控制允许连接到 MySQL 数据库的最大数量。如果状态变量 connection_errors_max_connections 不为零,并且一直增长,就说明不断有连接请求因数据库连接数已达到最大允许的值而失败,应考虑增大max_connections 的值。

MySQL 最大可支持的数据库连接取决于很多因素,包括给定操作系统平台线程库的质量、内存大小、每个连接的符合以及期望的响应时间等。在 Linux 平台下,MySQL 支持 500~1000 个连接不是难事,如果内存足够,不考虑响应时间,甚至能达到上万个连接。而在 windows 平台下,受其所用线程库的影响,最大连接数有以下限制:

(open tables * 2 + open connections) < 2048

每个session 操作 MySQL 数据库表都需要占用文件描述符,数据库连接本身也要占用文件描述符,因此,在增大 max_connections 时,也要注意评估 open-files-limit (文件描述符)的设置是否够用。

二、调整 back_log

back_log 参数控制 MySQL 监听 tcp 端口时设置的积压请求栈大小,5.6.6版本以前的默认值是 50,5.6.6 版本以后的默认值是 50 + (max_connections/5),但最大不能超过 900。

如果需要数据库在较短时间内处理大量连接请求,可以考虑适当增大 back_log 的值。

三、调整 table_open_cache

每一个 sql 执行线程至少都要打开一个表缓存,参数 table_open_cache 控制所有 sql 执行线程可打开表缓存的数量。这个参数的值应根据最大连接数 max_connections 以及每个连接执行关联查询中所涉及表的最大个数(用 N 表示)来设定:

max_connection * N

在未执行 flush tables 命令的情况下,如果 MySQL 状态值 opened_tables 的值较大,就说明 table_open_cache 设置的太小,应适当增大。增大 table_open_cache 的值,会增加 MySQL 对文件描述符的使用量,因此,也要注意评估 open-files-limit 的设置是或否够用。

四、调整 thread_cache_size

为加快连接数据库的速度,MySQL 会缓存一定数量的客户服务线程以备重用,通过参数 thread_cache_size 可控制 MySQL 缓存客户端线程的数量。
可以通过计算线程 cache 的失效率 threads_created / connections 来衡量 thread_cahce_size 的设置是否合适,该值越接近 1,说明线程 cache 命中率越低,应考虑适当增加 thread_cahce_size 的值。

五、innodb_lock_wait_timeout 的设置

参数 innodb_lock_wait_timeout 可以控制 innodb 事务等待行锁的时间,默认值是 50ms,可以根据需要动态设置。对于需要快速反馈的交互式应用,可以将行锁等待超时时间调大,以避免发生大的回滚操作。

Netstat命令详解(windows下)

Netstat 用于显示与IP 、TCP 、UDP 和ICMP 协议相关的统计数据,一般用于检验本机各端口的网络连接情况。 

     如果你的计算机有时候接收到的数据报导致出错数据或故障,你不必感到奇怪,TCP/IP 可以容许这些类型的错误,并能够自动重发数据报。但如果累计的出错情况数目占到所接收的IP 数据报相当大的百分比,或者它的数目正迅速增加,那么你就应该使用Netstat 查一查为什么会出现这些情况了。

Netstat 详细参数列表
(Winxp )
C:\>netstat /?
显示协议统计信息和当前 TCP/IP 网络连接。
NETSTAT [-a] [-b] [-e] [-n] [-o] [-p proto] [-r] [-s] [-v] [interval]
  -a            显示所有连接和监听端口。 
  -b            显示包含于创建每个连接或监听端口的可执行组件。在某些情况下已知可执行组件
                拥有多个独立组件,并且在这些情况下包含于创建连接或监听端口的组件序列被显示。 
                这种情况下,可执行组件名在底部的[]中,顶部是其调用的组件,等等,直到 TCP/IP
                 部分。注意此选项可能需要很长时间,如果没有足够权限可能失败。 

  -e            显示以太网统计信息。此选项可以与 -s
                选项组合使用。 

  -n            以数字形式显示地址和端口号。 
  -o            显示与每个连接相关的所属进程 ID 。 
  -p proto      显示 proto 指定的协议的连接;proto 可以是 
                下列协议之一: TCP 、UDP 、TCPv6 或 UDPv6 。 
                如果与 -s 选项一起使用以显示按协议统计信息,proto 可以是下列协议之一:
                IP 、IPv6 、ICMP 、ICMPv6 、TCP 、TCPv6 、UDP 或 UDPv6 。 

  -r            显示路由表。 
  -s            显示按协议统计信息。默认地,显示 IP 、 
                IPv6 、ICMP 、ICMPv6 、TCP 、TCPv6 、UDP 和 UDPv6 的统计信息; 
                -p 选项用于指定默认情况的子集。 
  -v            与 -b 选项一起使用时将显示包含于 
                为所有可执行组件创建连接或监听端口的 
                组件。 
  interval      重新显示选定统计信息,每次显示之间 
                暂停时间间隔( 以秒计) 。按 CTRL+C 停止重新 
                显示统计信息。如果省略,netstat 显示当前 
                配置信息( 只显示一次)
(Win2000 )
C:\>netstat /?
Displays protocol statistics and current TCP/IP network connections.
NETSTAT [-a] [-e] [-n] [-s] [-p proto] [-r] [interval]
  -a            Displays all connections and listening ports.
  -e            Displays Ethernet statistics. This may be combined with the -s
                option.
  -n            Displays addresses and port numbers in numerical form.
  -p proto      Shows connections for the protocol specified by proto; proto
                may be TCP or UDP.  If used with the -s option to display
                per-protocol statistics, proto may be TCP, UDP, or IP.
  -r            Displays the routing table.
  -s            Displays per-protocol statistics.  By default, statistics are
                shown for TCP, UDP and IP; the -p option may be used to specify
                a subset of the default.
  interval      Redisplays selected statistics, pausing interval seconds
                between each display.  Press CTRL+C to stop redisplaying
                statistics.  If omitted, netstat will print the current
                configuration information once.

Netstat 的一些常用选项 
 
netstat -s ——本选项能够按照各个协议分别显示其统计数据。如果你的应用程序(如Web 浏览器)运行速度比较慢,或者不能显示Web 页之类的数据,那么你就可以用本选项来查看一下所显示的信息。你需要仔细查看统计数据的各行,找到出错的关键字,进而确定问题所在。 


netstat -e ——本选项用于显示关于以太网的统计数据。它列出的项目包括传送的数据报的总字节数、错误数、删除数、数据报的数量和广播的数量。这些统计数据既有发送的数据报数量,也有接收的数据报数量。这个选项可以用来统计一些基本的网络流量。 


netstat -r ——本选项可以显示关于路由表的信息,类似于后面所讲使用route print 命令时看到的 信息。除了显示有效路由外,还显示当前有效的连接。 


netstat -a ——本选项显示一个所有的有效连接信息列表,包括已建立的连接(ESTABLISHED ),也包括监听连接请求(LISTENING )的那些连接,断开连接(CLOSE_WAIT )或者处于联机等待状态的(TIME_WAIT )等 


netstat -n ——显示所有已建立的有效连接。
 
    微软公司故意将这个功能强大的命令隐藏起来是因为它对于普通用户来说有些复杂。我们已经知道:Netstat 它可以用来获得你的系统网络连接的信息(使用的端口,在使用的协议等 ),收到和发出的数据,被连接的远程系统的端口,Netstat 在内存中读取所有的网络信息。
    在Internet RFC 标准中,Netstat 的定义是: Netstat 是在内核中访问网络及相关信息的程序,它能提供TCP 连接,TCP 和UDP 监听,进程内存管理的相关报告。
    对于好奇心极强的人来说,紧紧有上面的理论是远远不够的,接下来我们来详细的解释一下各个参数的使用,看看执行之后会发生什么,显示的信息又是什么意思,好了,废话不说了,让我们一起来实践一下吧:)
C:\>netstat -a
Active Connections
  Proto  Local Address          Foreign Address        State
  TCP    Eagle:ftp              Eagle:0                LISTENING
  TCP    Eagle:telnet           Eagle:0                LISTENING
  TCP    Eagle:smtp             Eagle:0                LISTENING
  TCP    Eagle:http             Eagle:0                LISTENING
  TCP    Eagle:epmap            Eagle:0                LISTENING
  TCP    Eagle:https            Eagle:0                LISTENING
  TCP    Eagle:microsoft-ds     Eagle:0                LISTENING
  TCP    Eagle:1030             Eagle:0                LISTENING
  TCP    Eagle:6059             Eagle:0                LISTENING
  TCP    Eagle:8001             Eagle:0                LISTENING
  TCP    Eagle:8005             Eagle:0                LISTENING
  TCP    Eagle:8065             Eagle:0                LISTENING
  TCP    Eagle:microsoft-ds     localhost:1031         ESTABLISHED
  TCP    Eagle:1031             localhost:microsoft-ds  ESTABLISHED
  TCP    Eagle:1040             Eagle:0                LISTENING
  TCP    Eagle:netbios-ssn      Eagle:0                LISTENING
  TCP    Eagle:1213             218.85.139.65:9002     CLOSE_WAIT
  TCP    Eagle:2416             219.133.63.142:https   CLOSE_WAIT
  TCP    Eagle:2443             219.133.63.142:https   CLOSE_WAIT
  TCP    Eagle:2907             192.168.1.101:2774     CLOSE_WAIT
  TCP    Eagle:2916             192.168.1.101:telnet   ESTABLISHED
  TCP    Eagle:2927             219.137.227.10:4899    TIME_WAIT
  TCP    Eagle:2928             219.137.227.10:4899    TIME_WAIT
  TCP    Eagle:2929             219.137.227.10:4899    ESTABLISHED
  TCP    Eagle:3455             218.85.139.65:9002     ESTABLISHED
  TCP    Eagle:netbios-ssn      Eagle:0                LISTENING
  UDP    Eagle:microsoft-ds     *:*
  UDP    Eagle:1046             *:*
  UDP    Eagle:1050             *:*
  UDP    Eagle:1073             *:*
  UDP    Eagle:1938             *:*
  UDP    Eagle:2314             *:*
  UDP    Eagle:2399             *:*
  UDP    Eagle:2413             *:*
  UDP    Eagle:2904             *:*
  UDP    Eagle:2908             *:*
  UDP    Eagle:3456             *:*
  UDP    Eagle:4000             *:*
  UDP    Eagle:4001             *:*
  UDP    Eagle:6000             *:*
  UDP    Eagle:6001             *:*
  UDP    Eagle:6002             *:*
  UDP    Eagle:6003             *:*
  UDP    Eagle:6004             *:*
  UDP    Eagle:6005             *:*
  UDP    Eagle:6006             *:*
  UDP    Eagle:6007             *:*
  UDP    Eagle:6008             *:*
  UDP    Eagle:6009             *:*
  UDP    Eagle:6010             *:*
  UDP    Eagle:6011             *:*
  UDP    Eagle:1045             *:*
  UDP    Eagle:1051             *:*
  UDP    Eagle:netbios-ns       *:*
  UDP    Eagle:netbios-dgm      *:*
  UDP    Eagle:netbios-ns       *:*
  UDP    Eagle:netbios-dgm      *:*
 
我们拿其中一行来解释吧:
Proto  Local Address          Foreign Address        State
TCP    Eagle:2929             219.137.227.10:4899    ESTABLISHED
 
协议(Proto ):TCP ,指是传输层通讯协议(什么?不懂?请用baidu 搜索"TCP" ,OSI 七层和TCP/IP 四层可是基础^_^ ) 
本地机器名(Local  Address ):Eagle ,俗称计算机名了,安装系统时设置的,可以在“我的电脑”属性中修改,本地打开并用于连接的端口:2929 )    
远程机器名(Foreign  Address ): 
219.137.227.10
远程端口: 
4899  
状态:ESTABLISHED  
 
状态列表
LISTEN   :在监听状态中。    
ESTABLISHED :已建立联机的联机情况。 

TIME_WAIT :该联机在目前已经是等待的状态。 
 
-a 参数常用于获得你的本地系统开放的端口,用它您可以自己检查你的系统上有没有被安装木马(ps :有很多好程序用来检测木马,但你的目的是想成为真正的hacker ,手工检测要比只按一下“scan ”按钮好些---- 仅个人观点)。如果您Netstat 你自己的话,发现下面的信息: 
   

   Port 12345(TCP) Netbus 
   
Port 31337(UDP) Back Orifice 
   

  祝贺! 您中了最常见的木马(^_^ ,上面4899 是我连别人的,而且这个radmin 是商业软件,目前我最喜欢的远程控制软件) 
  如果你需要木马及其端口列表的话,去国内的H 站找找,或者baidu ,google 吧 

   

   ***************************************************************** 
   

  # 一些原理:也许你有这样的问题:“在机器名后的端口号代表什么? 
  例子: 
Eagle:2929
  小于1024 的端口通常运行一些网络服务,大于1024 的端口用来与远程机器建立连接。   

  *****************************************************************
 
继续我们的探讨,使用-n 参数。( Netstat -n) 
  Netstat -n 基本上是-a 参数的数字形式:
 
C:\>netstat -n
Active Connections
  Proto  Local Address          Foreign Address        State
  TCP    127.0.0.1:445          127.0.0.1:1031         ESTABLISHED
  TCP    127.0.0.1:1031         127.0.0.1:445          ESTABLISHED
  TCP    192.168.1.180:1213     218.85.139.65:9002     CLOSE_WAIT
  TCP    192.168.1.180:2416     219.133.63.142:443     CLOSE_WAIT
  TCP    192.168.1.180:2443     219.133.63.142:443     CLOSE_WAIT
  TCP    192.168.1.180:2907     192.168.1.101:2774     CLOSE_WAIT
  TCP    192.168.1.180:2916     192.168.1.101:23       ESTABLISHED
  TCP    192.168.1.180:2929     219.137.227.10:4899    ESTABLISHED
  TCP    192.168.1.180:3048     192.168.1.1:8004       SYN_SENT
  TCP    192.168.1.180:3455     218.85.139.65:9002     ESTABLISHED
 
-a  和 -n  是最常用的两个,据我不完全测试得出以下结果:
1. -n 显示用数字化主机名,即IP 地址,而不是compute_name 【eagle 】
2. -n  只显示TCP 连接(没有在哪里见过微软的相关文档,有哪个朋友见到的话,记得告诉我喔^_^ )
     得到IP 等于得到一切,它是最容易使机器受到攻击的东东,所以隐藏自己IP ,获得别人的IP 对hacker来说非常重要,现在隐藏IP 技术很流行,但那些隐藏工具或服务真的让你隐身吗?我看不见得,呵呵,代理,跳板不属于今天讨论,一个获取对方IP 的简单例子请参考我前面的文章【用DOS 命令查QQ 好友IP 地址 】 
 
-a 和 -n 是最常用的命令,如果要显示一些协议的更详细信息,就要用-p 这个参数了,它其实是-a  和 -n 的一个变种 ,我们来看一个实例,你就明白了:【netstat -p @@@ 其中@@@ 为TCP 或者UDP 】
C:\>netstat -p tcp
Active Connections
  Proto  Local Address          Foreign Address        State
  TCP    Eagle:microsoft-ds     localhost:1031         ESTABLISHED
  TCP    Eagle:1031             localhost:microsoft-ds  ESTABLISHED
  TCP    Eagle:1213             218.85.139.65:9002     CLOSE_WAIT
  TCP    Eagle:2416             219.133.63.142:https   CLOSE_WAIT
  TCP    Eagle:2443             219.133.63.142:https   CLOSE_WAIT
  TCP    Eagle:2907             192.168.1.101:2774     CLOSE_WAIT
  TCP    Eagle:2916             192.168.1.101:telnet   ESTABLISHED
  TCP    Eagle:2929             219.137.227.10:4899    ESTABLISHED
  TCP    Eagle:3455             218.85.139.65:9002     ESTABLISHED
  
  继续我们的参数讲解 -e
    含义:本选项用于显示关于以太网的统计数据。它列出的项目包括传送的数据报的总字节数、错误数、删除数、数据报的数量和广播的数量 。这些统计数据既有发送的数据报数量,也有接收的数据报数量。这个选项可以用来统计一些基本的网络流量。
C:\>netstat -e
Interface Statistics
                           Received            Sent
Bytes                     143090206        44998789
Unicast packets              691805          363603
Non-unicast packets          886526            2386
Discards                          0               0
Errors                            0               0
Unknown protocols              4449
    若接收错和发送错接近为零或全为零,网络的接口无问题。但当这两个字段有100 个以上的出错分组时就可以认为是高出错率了。高的发送错表示本地网络饱和或在主机与网络之间有不良的物理连接;   高的接收错表示整体网络饱和、本地主机过载或物理连接有问题,可以用Ping 命令统计误码率,进一步确定故障的程度。netstat -e  和ping 结合使用能解决一大部分网络故障。
 
    接下来我们开始讲解两个比较复杂的参数 -r   -s ,也正因为如此,笔者把他放到最后讲解,这里面可能会涉及到其他方面的知识,以后在我的博客中将会继续写出来,呵呵,最近比较忙
   
-r 是用来显示路由表信息,我们来看例子:
C:\>netstat -r
Route Table (路由表) 
===========================================================================
Interface List
 (网络接口列表) 
0x1 ........................... MS TCP Loopback interface
0x10003 ...00 0c f1 02 76 81 ...... Intel(R) PRO/Wireless LAN 2100 3B Mini PCI
dapter
0x10004 ...00 02 3f 00 05 cb ...... Realtek RTL8139/810x Family Fast Ethernet
C
===========================================================================
===========================================================================
Active Routes:
 (动态路由) 
Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0    192.168.1.254   192.168.1.181       30
          0.0.0.0          0.0.0.0    192.168.1.254   192.168.1.180       20
        127.0.0.0        255.0.0.0        127.0.0.1       127.0.0.1       1
      192.168.1.0    255.255.255.0    192.168.1.180   192.168.1.180       20
      192.168.1.0    255.255.255.0    192.168.1.181   192.168.1.181       30
    192.168.1.180  255.255.255.255        127.0.0.1       127.0.0.1       20
    192.168.1.181  255.255.255.255        127.0.0.1       127.0.0.1       30
    192.168.1.255  255.255.255.255    192.168.1.180   192.168.1.180       20
    192.168.1.255  255.255.255.255    192.168.1.181   192.168.1.181       30
        224.0.0.0        240.0.0.0    192.168.1.180   192.168.1.180       20
        224.0.0.0        240.0.0.0    192.168.1.181   192.168.1.181       30
  255.255.255.255  255.255.255.255    192.168.1.180   192.168.1.180       1
  255.255.255.255  255.255.255.255    192.168.1.181   192.168.1.181       1
Default Gateway:     192.168.1.254
 (默认网关) 
===========================================================================
Persistent Routes:
 (静态路由) 
  None
C:\>
 
-s 参数的作用前面有详细的说明,来看例子
C:\>netstat -s
IPv4 Statistics        (IP 统计结果)     
  Packets Received                   = 369492 (接收包数) 
  Received Header Errors             = 0 (接收头错误数) 
  Received Address Errors            = 2 (接收地址错误数) 
  Datagrams Forwarded                = 0 (数据报递送数) 
  Unknown Protocols Received         = 0 (未知协议接收数) 
  Received Packets Discarded         = 4203 (接收后丢弃的包数) 
  Received Packets Delivered         = 365287 (接收后转交的包数) 
  Output Requests                    = 369066 (请求数) 
  Routing Discards                   = 0 (路由丢弃数 ) 
  Discarded Output Packets           = 2172 (包丢弃数) 
  Output Packet No Route             = 0 (不路由的请求包) 
  Reassembly Required                = 0 (重组的请求数 ) 
  Reassembly Successful              = 0 (重组成功数) 
  Reassembly Failures                = 0 (重组失败数) 
  Datagrams Successfully Fragmented  = 0 (分片成功的数据报数 ) 
  Datagrams Failing Fragmentation    = 0 (分片失败的数据报数 ) 
  Fragments Created                  = 0 (分片建立数)
ICMPv4 Statistics (ICMP 统计结果)包括Received 和Sent 两种状态
                            Received    Sent
  Messages                  285         784 (消息数 ) 

  Errors                    0           0 (错误数) 
  Destination Unreachable   53          548 (无法到达主机数目) 
  Time Exceeded             0           0 (超时数目) 
  Parameter Problems        0           0 (参数错误) 
  Source Quenches           0           0 (源夭折数 ) 
  Redirects                 0           0 (重定向数) 
  Echos                     25          211 (回应数) 
  Echo Replies              207         25 (回复回应数) 
  Timestamps                0           0 (时间戳数) 
  Timestamp Replies         0           0 (时间戳回复数) 
  Address Masks             0           0 (地址掩码数 ) 
  Address Mask Replies      0           0 (地址掩码回复数)
TCP Statistics for IPv4 (TCP 统计结果)
  Active Opens                        = 5217 (主动打开数 ) 
  Passive Opens                       = 80 (被动打开数 ) 
  Failed Connection Attempts          = 2944 (连接失败尝试数 ) 
  Reset Connections                   = 529 (复位连接数 ) 
  Current Connections                 = 9 (当前连接数目) 
  Segments Received                   = 350143 (当前已接收的报文数) 
  Segments Sent                       = 347561 (当前已发送的报文数) 
  Segments Retransmitted              = 6108 (被重传的报文数目)
UDP Statistics for IPv4 (UDP 统计结果)
  Datagrams Received    = 14309 (接收的数据包) 
  No Ports              = 1360 (无端口数) 
  Receive Errors        = 0 (接收错误数) 
  Datagrams Sent        = 14524 (数据包发送数)
C:\>

如何在删除ibdata1和ib_logfile的情况下恢复MySQL数据库

有个朋友对公司内部使用的一个MySQL实例开启binlog,但是在启动的过程中失败了(他也没提,为何会失败),在启动失败后,他删除了ibdata1和ib_logfile,后来,能正常启动了,但所有的表通过show tables能看到,但是select的过程中却报“Table doesn't exist”。

于是,建议他试试可传输表空间。

同时,自己也测试了下,确实可行。

测试版本 MySQL 5.6.32 社区版

 

恢复的基本步骤

1. 将原来的数据文件COPY到其它目录下。

2. 创建同名表,表结构必须保持一致。

3. 导出表空间

mysql> ALTER TABLE t DISCARD TABLESPACE;

4. 将原来的数据文件COPY回来

5. 导入表空间

mysql> ALTER TABLE t IMPORT TABLESPACE

 

下面的演示会略为复杂,主要是还原整个场景,并针对上述步骤中的2,4做了一个测试。

 

首先,创建测试数据

在这里创建两张表。之所以创建两张相同的表是为了方便后续的测试。

复制代码
mysql> create table t1(id int,hiredate datetime);
Query OK, 0 rows affected (0.14 sec)

mysql> create table t2(id int,hiredate datetime);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t1 values(1,now());
Query OK, 1 row affected (0.06 sec)

mysql> insert into t1 values(2,now());
Query OK, 1 row affected (0.00 sec)

mysql> insert into t2 values(1,now());
Query OK, 1 row affected (0.00 sec)

mysql> insert into t2 values(2,now());
Query OK, 1 row affected (0.00 sec)
复制代码

 

关闭数据库

# /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysqladmin shutdown -uroot -p123456 -h127.0.0.1 -P3310

 

删除ibdata1,ib_logfile0和ib_logfile1

复制代码
[root@localhost data]# cd /data/
[root@localhost data]# ls
auto.cnf  ib_logfile0  localhost.localdomain.err  mysql_upgrade_info  test
ibdata1   ib_logfile1  mysql                      performance_schema
[root@localhost data]# rm -rf ibdata1 
[root@localhost data]# rm -rf ib_logfile*[root@localhost data]# ls
auto.cnf  localhost.localdomain.err  mysql  mysql_upgrade_info  performance_schema  test
复制代码

 

重新启动数据库

# /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysqld --defaults-file=/usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/my.cnf &

并没有报错

启动过程中的日志信息如下:

复制代码
# 2016-08-18 11:13:18 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2016-08-18 11:13:18 0 [Note] /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysqld (mysqld 5.6.32) starting as process 3948 ...
2016-08-18 11:13:18 3948 [Note] Plugin 'FEDERATED' is disabled.
2016-08-18 11:13:18 3948 [Note] InnoDB: Using atomics to ref count buffer pool pages
2016-08-18 11:13:18 3948 [Note] InnoDB: The InnoDB memory heap is disabled
2016-08-18 11:13:18 3948 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2016-08-18 11:13:18 3948 [Note] InnoDB: Memory barrier is not used
2016-08-18 11:13:18 3948 [Note] InnoDB: Compressed tables use zlib 1.2.3
2016-08-18 11:13:18 3948 [Note] InnoDB: Using Linux native AIO
2016-08-18 11:13:18 3948 [Note] InnoDB: Using CPU crc32 instructions
2016-08-18 11:13:18 3948 [Note] InnoDB: Initializing buffer pool, size = 128.0M
2016-08-18 11:13:19 3948 [Note] InnoDB: Completed initialization of buffer pool
2016-08-18 11:13:19 3948 [Note] InnoDB: The first specified data file ./ibdata1 did not exist: a new database to be created!
2016-08-18 11:13:19 3948 [Note] InnoDB: Setting file ./ibdata1 size to 12 MB
2016-08-18 11:13:19 3948 [Note] InnoDB: Database physically writes the file full: wait...
2016-08-18 11:13:19 3948 [Note] InnoDB: Setting log file ./ib_logfile101 size to 48 MB
2016-08-18 11:13:21 3948 [Note] InnoDB: Setting log file ./ib_logfile1 size to 48 MB
2016-08-18 11:13:22 3948 [Note] InnoDB: Renaming log file ./ib_logfile101 to ./ib_logfile0
2016-08-18 11:13:22 3948 [Warning] InnoDB: New log files created, LSN=45781
2016-08-18 11:13:22 3948 [Note] InnoDB: Doublewrite buffer not found: creating new
2016-08-18 11:13:22 3948 [Note] InnoDB: Doublewrite buffer created
2016-08-18 11:13:22 3948 [Note] InnoDB: 128 rollback segment(s) are active.
2016-08-18 11:13:22 3948 [Warning] InnoDB: Creating foreign key constraint system tables.
2016-08-18 11:13:22 3948 [Note] InnoDB: Foreign key constraint system tables created
2016-08-18 11:13:22 3948 [Note] InnoDB: Creating tablespace and datafile system tables.
2016-08-18 11:13:22 3948 [Note] InnoDB: Tablespace and datafile system tables created.
2016-08-18 11:13:22 3948 [Note] InnoDB: Waiting for purge to start
2016-08-18 11:13:22 3948 [Note] InnoDB: 5.6.32 started; log sequence number 0
2016-08-18 11:13:22 3948 [Note] Server hostname (bind-address): '*'; port: 3310
2016-08-18 11:13:23 3948 [Note] IPv6 is available.
2016-08-18 11:13:23 3948 [Note]   - '::' resolves to '::';
2016-08-18 11:13:23 3948 [Note] Server socket created on IP: '::'.
2016-08-18 11:13:23 3948 [Note] Event Scheduler: Loaded 0 events
2016-08-18 11:13:23 3948 [Note] /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysqld: ready for connections.
Version: '5.6.32'  socket: '/data/mysql.sock'  port: 3310  MySQL Community Server (GPL)
复制代码

可见,在启动的过程中,MySQL会重建ibdata1和redo log。

 

登录mysql客户端,看之前创建的t1,t2是否能访问

# /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysql -h127.0.0.1 -p123456 -uroot -P3310

复制代码
mysql> use test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| t1             |
| t2             |
+----------------+
2 rows in set (0.00 sec)

mysql> select * from t1;
ERROR 1146 (42S02): Table 'test.t1' doesn't exist
复制代码

 

通过show tables能查看有t1表存在,但表中的具体内容则无法查看

同时,错误日志中输出以下信息

2016-08-18 11:15:13 3948 [Warning] InnoDB: Cannot open table test/t1 from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.

 

将数据目录下的test目录中的t1,t2表的数据文件和表定义文件COPY到其它地方

复制代码
[root@localhost test]# cd /data/test/
[root@localhost test]# ll
total 216
-rw-rw---- 1 mysql mysql  8594 Aug 18 11:06 t1.frm
-rw-rw---- 1 mysql mysql 98304 Aug 18 11:07 t1.ibd
-rw-rw---- 1 mysql mysql  8594 Aug 18 11:06 t2.frm
-rw-rw---- 1 mysql mysql 98304 Aug 18 11:07 t2.ibd
[root@localhost test]# mv * /backup/
[root@localhost test]# ls
[root@localhost test]# ll /backup/
total 216
-rw-rw---- 1 mysql mysql  8594 Aug 18 11:06 t1.frm
-rw-rw---- 1 mysql mysql 98304 Aug 18 11:07 t1.ibd
-rw-rw---- 1 mysql mysql  8594 Aug 18 11:06 t2.frm
-rw-rw---- 1 mysql mysql 98304 Aug 18 11:07 t2.ibd
复制代码

 

登录客户端,创建t1和t2表,注意表结构和之前的必须保持一致

细心的童鞋会发现,下面的创表语句和刚开始的创表语句并不一样,列名不一致,这个其实是为了后续的测试

mysql> show tables;
Empty set (0.00 sec)

mysql> create table t1(id_1 int,hiredate_1 datetime);
ERROR 1146 (42S02): Table 'test.t1' doesn't exist

明明已经手动移除了,为什么创建表的时候还报这个错误呢?

接下来,可先执行个drop table操作

mysql> drop table t1;
ERROR 1051 (42S02): Unknown table 'test.t1'
mysql> create table t1(id_1 int,hiredate_1 datetime);
Query OK, 0 rows affected (0.07 sec)

 

对于t2表,我们定义一个不同的表结构,看是否可行?

mysql> drop table t2;
ERROR 1051 (42S02): Unknown table 'test.t2'
mysql> create table t2(id_1 int);
Query OK, 0 rows affected (0.01 sec)

 

导出表空间

mysql> ALTER TABLE t1 DISCARD TABLESPACE;
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE t2 DISCARD TABLESPACE;
Query OK, 0 rows affected (0.00 sec)

这个时候,数据目录下的test目录下,数据文件没有了,只剩下了表结构文件

[root@localhost test]# ls
t1.frm  t2.frm

 

导入表空间

首先对t1表进行测试

在这里,测试如下两种情况

1. 新的t1.frm+旧的t1.ibd

2. 旧的t1.frm+旧的t1.ibd

 

第一种情况

只是将t1表的数据文件COPY回来

[root@localhost test]# cp /backup/t1.ibd .
[root@localhost test]# chown mysql.mysql t1.ibd 

 

导入t1表的表空间

复制代码
mysql> ALTER TABLE t1 IMPORT TABLESPACE;
Query OK, 0 rows affected, 1 warning (0.21 sec)

mysql> show warnings;
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                 |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+
| Warning | 1810 | InnoDB: IO Read error: (2, No such file or directory) Error opening './test/t2.cfg', will attempt to import without schema verification |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
复制代码

 

查看t1表是否能访问

复制代码
mysql> select * from t1;
+------+---------------------+
| id_1 | hiredate_1          |
+------+---------------------+
|    1 | 2016-08-18 17:45:02 |
|    2 | 2016-08-18 17:45:02 |
+------+---------------------+
2 rows in set (0.00 sec)

mysql> flush table t1;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1;
+------+---------------------+
| id_1 | hiredate_1          |
+------+---------------------+
|    1 | 2016-08-18 17:45:02 |
|    2 | 2016-08-18 17:45:02 |
+------+---------------------+
2 rows in set (0.00 sec)
复制代码

喔,确实能访问,注意观察,表的列名与新的创表语句保持一致。

在这里之所以使用flush table操作,是为了刷新内存中的表定义。

 

下面看看t1的第二种情况,旧的t1.frm+旧的t1.ibd

mysql> ALTER TABLE t1 DISCARD TABLESPACE;
Query OK, 0 rows affected (0.00 sec)
[root@localhost test]# cp /backup/t1.frm .
cp: overwrite `./t1.frm'? y
[root@localhost test]# cp /backup/t1.ibd .
[root@localhost test]# chown mysql.mysql t1.frm 
[root@localhost test]# chown mysql.mysql t1.ibd 
复制代码
mysql> ALTER TABLE t1 import TABLESPACE;
Query OK, 0 rows affected, 1 warning (0.04 sec)

mysql> select * from t1;
+------+---------------------+
| id_1 | hiredate_1          |
+------+---------------------+
|    1 | 2016-08-18 17:45:02 |
|    2 | 2016-08-18 17:45:02 |
+------+---------------------+
2 rows in set (0.00 sec)

mysql> flush table t1;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1;
+------+---------------------+
| id   | hiredate            |
+------+---------------------+
|    1 | 2016-08-18 17:45:02 |
|    2 | 2016-08-18 17:45:02 |
+------+---------------------+
2 rows in set (0.00 sec)
复制代码

第一次查询的时候还是新的列名,对表进行flush后,就恢复到原来的列名了。

 

下面来看看t2表的导入情况

因为t2表的表结构发生了改变,在这里,也是测试如下两种情况

1. 新的t2.frm+旧的t2.ibd

2. 旧的t2.frm+旧的t2.ibd

 

首先,只是导入t2表的数据文件

复制代码
[root@localhost test]# cp /backup/t2.ibd .
[root@localhost test]# ll
total 216
-rw-rw---- 1 mysql mysql  8594 Aug 18 17:55 t1.frm
-rw-r----- 1 mysql mysql 98304 Aug 18 18:00 t1.ibd
-rw-rw---- 1 mysql mysql  8556 Aug 18 17:52 t2.frm
-rw-r----- 1 root  root  98304 Aug 18 18:10 t2.ibd
[root@localhost test]# chown mysql.mysql t2.ibd 
复制代码

 

导入t2表的表空间进行测试

复制代码
mysql> ALTER TABLE t2 import TABLESPACE;
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> select * from t2;
+------+
| id_1 |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

mysql> flush table t2;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t2;
+------+
| id_1 |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)
复制代码

从结果可以看出,只能读出第一列。

 

下面测试第二种情况,旧的t2.frm和t2.ibd

mysql> ALTER TABLE t2 DISCARD TABLESPACE;
Query OK, 0 rows affected (0.06 sec)
[root@localhost test]# rm -rf t2.frm 
[root@localhost test]# cp /backup/t2.frm .
[root@localhost test]# cp /backup/t2.ibd .
[root@localhost test]# chown mysql.mysql t2.frm 
[root@localhost test]# chown mysql.mysql t2.ibd 
复制代码
mysql> ALTER TABLE t2 import TABLESPACE;
Query OK, 0 rows affected, 1 warning (0.09 sec)

mysql> select * from t2;
+------+
| id_1 |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

mysql> flush table t2;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t2;
ERROR 1146 (42S02): Table 'test.t2' doesn't exist
复制代码

在重新刷新后,就出现错误了,个人感觉,这个和系统表空间中的数据字典信息有关。

 

实际上,后续还测试了一下,如果将hiredate的列定义为varchar,则无论是使用之前的frm文件还是之后的,在导入表空间,进行查询时,数据库直接挂掉。

复制代码
mysql> create table t1(id int,hiredate varchar(10));
Query OK, 0 rows affected (0.05 sec)

mysql> ALTER TABLE t1 DISCARD TABLESPACE;
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE t1 import TABLESPACE;
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> select * from t1;
ERROR 2013 (HY000): Lost connection to MySQL server during query
复制代码

 

结论

经过上面的一系列测试,可以看到

1. 使用可传输表空间,可以解决在删除ibdata1和ib_logfile的情况下恢复MySQL数据库,当然,本文测试的前提是数据库正常关闭下删除的ibdata1和ib_logfile。

2. 使用可传输表空间,建议新建表的表结构和原来的表结构完全一致,同时,在导入表空间前,只需COPY回原来的数据文件,即ibd。

 

事实上,在数据库正常关闭下删除ibdata1,会导致mysql库中的以下几张表无法访问

复制代码
mysql> select table_name from information_schema.tables  where table_schema='mysql' and engine='innodb';
+----------------------+
| table_name           |
+----------------------+
| innodb_index_stats   |
| innodb_table_stats   |
| slave_master_info    |
| slave_relay_log_info |
| slave_worker_info    |
+----------------------+
5 rows in set (0.00 sec)

mysql> select * from mysql.innodb_index_stats;
ERROR 1146 (42S02): Table 'mysql.innodb_index_stats' doesn't exist
mysql> select * from mysql.innodb_table_stats;
ERROR 1146 (42S02): Table 'mysql.innodb_table_stats' doesn't exist
mysql> select * from mysql.slave_master_info;
ERROR 1146 (42S02): Table 'mysql.slave_master_info' doesn't exist
mysql> select * from mysql.slave_relay_log_info;
ERROR 1146 (42S02): Table 'mysql.slave_relay_log_info' doesn't exist
mysql> select * from mysql.slave_worker_info;
ERROR 1146 (42S02): Table 'mysql.slave_worker_info' doesn't exist
复制代码

同时,错误日志中报如下信息

复制代码
2016-08-19 12:10:18 3041 [Warning] InnoDB: Cannot open table mysql/innodb_index_stats from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.
2016-08-19 12:10:26 3041 [Warning] InnoDB: Cannot open table mysql/innodb_table_stats from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.
2016-08-19 12:10:34 3041 [Warning] InnoDB: Cannot open table mysql/slave_master_info from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.
2016-08-19 12:10:40 3041 [Warning] InnoDB: Cannot open table mysql/slave_relay_log_info from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.
2016-08-19 12:10:46 3041 [Warning] InnoDB: Cannot open table mysql/slave_worker_info from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.
复制代码

 

要解决这个问题,只能重建这些表。

 

参考

1. http://dev.mysql.com/doc/refman/5.6/en/tablespace-copying.html

2. http://dba.stackexchange.com/questions/48166/cannot-open-table-mysql-innodb-index-stats

 

About Us

Since 1996, our company has been focusing on domain name registration, web hosting, server hosting, website construction, e-commerce and other Internet services, and constantly practicing the concept of "providing enterprise-level solutions and providing personalized service support". As a Dell Authorized Solution Provider, we also provide hardware product solutions associated with the company's services.
 

Contact Us

Address: No. 2, Jingwu Road, Zhengzhou City, Henan Province

Phone: 0086-371-63520088 

QQ:76257322

Website: 800188.com

E-mail: This email address is being protected from spambots. You need JavaScript enabled to view it.