MySQL 5.5 主从复制的原理、过程
 
分为同步复制和异步复制,实际复制架构中大部分为异步复制。复制的基本过程如下: 
1)、Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;   2)、Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取指定日志指定位置之后的日志信息,返回给Slave的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的pos位置;   3)、Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的中继日志(relay-log)文件的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master.info文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log的哪个pos位置开始往后的日志内容,请发给我”; 4)、Slave的sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。    Slave端的双进程复制提升可靠性
Mysql为了解决这个风险并提高复制的性能,将Slave端的复制改为两个进程来完成。提出这个改进方案的人是Yahoo!的一位工程师“Jeremy Zawodny”。这样既解决了性能问题,又缩短了异步的延时时间,同时也减少了可能存在的数据丢失量。当然,即使是换成了现在这样两个线程处理以后,同样也还是存在Slave数据延时以及数据丢失的可能性的,毕竟这个复制是异步的。只要数据的更改不是在一个事物中,这些问题都是会存在的。如果要完全避免这些问题,就只能用mysql的cluster来解决了。不过mysql的cluster是内存数据库的解决方案,需要将所有数据都load到内存中,这样就对内存的要求就非常大了,对于一般的应用来说可实施性不是太大。 常用主从复制架构 
Mysql复制环境90%以上都是一个Master带一个或者多个Slave的架构模式,主要用于读压力比较大的应用的数据库端廉价扩展解决方案。因为只要master和slave的压力不是太大(尤其是slave端压力)的话,异步复制的延时一般都很少很少。尤其是自slave端的复制方式改成两个进程处理之后,更是减小了slave端的延时。而带来的效益是,对于数据实时性要求不是特别的敏感度的应用,只需要通过廉价的pc server来扩展slave的数量,将读压力分散到多台slave的机器上面,即可解决数据库端的读压力瓶颈。这在很大程度上解决了目前很多中小型网站的数据库压力瓶颈问题,甚至有些大型网站也在使用类似方案解决数据库瓶颈。 一、准备实验环境:
主(Master)机IP: 192.168.137.26
从(Slave) 机IP: 192.168.137.27
两MySQL服务器均是源码包编译安装 二、向主(Master)机添加远程登录的授权用户
1.向主(Master)服务器添加用户:
@ 用户名: slave4
@ 密 码: 789
@ 允许自: 192.168.137.27 机器登录 授权方式1: 此种授权是可远程登录Master,仅用于主从复制没有其它任何select insert update等权限【推荐】
mysql> grant replication slave on *.* to 'slave4'@'192.168.137.27' identified by '789'; 授权方式2: 此种授权是对用户不但可远程登录Master,还可拥有对Master包括主从复制的其它所有select insert update等权限
mysql> grant all on *.* to 'slave6'@'192.168.137.28' identified by '789'; 2.刷新授权表:
mysql> flush privileges; 3.查看授权结果:
mysql> show grants for 'slave4'@'192.168.137.27'; 4.测试从Slave端登录远程主(Master)机:
# /usr/local/mysql/bin/mysql -uslave4 -p789 -h192.168.137.26 5.从主(Master)机查看所有连接登录本机的客户端情况:
mysql> show processlist \G 三、主(Master)机配置
vi编辑打开mysql配置文件
# vi /usr/local/mysql/etc/my.cnf 找到从约第56行开始确认以下三项:
[mysqld]
log-bin=mysql-bin # 确认开启binlog日志
binlog_format=mixed # 确认binlog日志格式为mixd混合类型
server-id = 1 # 在整个主从架构内指定一个唯一的server-id,范围:1^32 四、从(Slave)机配置-【基本】
vi编辑打开mysql配置文件
# vi /usr/local/mysql/etc/my.cnf 找到从约第56行开始确认以下三项:
[mysqld]
log-bin=mysql-bin # 确认也开启binlog日志
binlog_format=mixed # 确认binlog日志格式为mixd混合类型
server-id = 2 # 在整个主从架构内指定一个唯一的server-id,范围:1^32 ◆ 从(Slave)机配置-【可选】
下面是生产阶段可能要用的功能,这些功能只能在从机的配置文件的[mysqld]区块里手工配置,无法通过 change master to ...命令实现。
1.白名单 - 只想复制某(些)个库:
replicate_do_db=zyyshop # 追加复制zyyshop库
replicate_do_db=test # 追加只复制test库
总结: 相当于只复制 zyyshop、test 两个库
如果采用完全在配置文件里配置主(Master)机信息的方法,此项须添加,否则可能导致mysqld启动不了 2.白名单 - 只想复制某(些)个库(的所有表)
replicate_wild_do_table=zyyshop.% # 追加复制zyyshop库的所有表
replicate_wild_do_table=test.% # 追加复制test库的所有表
总结:也是相当于只复制 zyyshop、test 两个库。 3.白名单 - 只想复制某(些)个库(的部分表)
replicate_wild_do_table=zyyshop.stu # 追加zyyshop.stu表
replicate_wild_do_table=test.project # 追加test.project表
总结:相当于只复制zyyshop.stu、test.project两个表。 4.黑名单 - 想忽略对mysql和test数据库的复制
replicate_ignore_db=mysql # 追加mysql库为忽略
replicate_ignore_db=test # 追加test库为忽略
总结:相当于将mysql和test两数据库追加到忽略列表,将不会被复制。 5.黑名单 - 想忽略对某些库的某些表的复制
replicate_wild_ignore_table=mysql.users # 追加mysql.users表为忽略
总结:本步骤是相当于追加了mysql.users具体的表被忽略,其它表照常会被复制。 6.如果想实现“主-->从-->从”的链式架构,因为在默认情况下,from主(Master)机copy过来的数据不会写入从(Slave)机的binlog日志里,
而是写入中继日志(localhost-relay-bin.00000x)里,所以本机如果还需要充当其它机器的主机,就将从主机复制来的数据写入从库时同
时也显式地写入本地binlog日志,添加如下配置:
log-slave-updates =1 五、在主(Master)机端操作:执行命令刷新主机binlog日志记录,查看主机的最后日志文件及最后pos起始点
mysql> flush logs;
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000009 | 107 | | |
+------------------+----------+--------------+------------------+ 六、在从(Slave)机启动slave服务
1.使用root用户登录到从(Slave)机
# /usr/local/mysql/bin/mysql -uroot -p123456 2.在从(Slave)上执行命令,动态改变连接到主(Master)机的配置,生成或更新master.info文件:
注: 在生产环境中,如果心跳感应到主机意外宕机,应用程序应该按预案选定出一台新主机,而其它的从机都需要执行一次下面
的 change master to ...语句,切换自己从属到新主机,这样比较灵活,操作的实质是更新master.info文件,查看此文件也
能发现MySQL其实是只能支持“一主多从”架构,而不能像Redis那样还可以支持多主一从架构。 mysql> change master to master_host='192.168.137.26', master_user='slave4', master_password='789', MASTER_LOG_FILE='mysql-bin.000009', MASTER_LOG_POS=107; 善于使用?查看详细选项
mysql> ? change master to 常用选项:
master_host='192.168.137.26' 远程主(Master)机IP
master_user='slave4', 登录远程主(Master)机 用户名
master_password='789', 登录远程主(Master)机 密码 不常用选项:
MASTER_LOG_FILE='mysql-bin.000009' 指定从哪个binlog文件复制(如果不加此参数默认是最早的binlog日志)
MASTER_LOG_POS=107 指定从哪个binlog文件的哪个pos点开始复制(如果不加此参数默认是最早的pos点)
MASTER_PORT=3306, 远程主(Master)机端口
MASTER_HEARTBEAT_PERIOD=60 多长时间探测一次主服务器是否在线 单位:秒
MASTER_CONNECT_RETRY=10; 无法连接主服务器的时候重试连接的间隔时间 单位:秒 3.启动IO线程和SQL线程,生成master.info文件,查看从(Slave)机状态:
mysql> start slave;
mysql> show slave status \G; 如果看到如下状态说明同步成功:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0 4.报错处理!如果“Slave_SQL_Running: No”,程序可能在slave上进行了写操作,也可能是slave机器重起后,事务回滚造成的。
解决方法一:
mysql> stop slave;
mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
mysql> start slave;
mysql> show slave status \G; 解决方法二:
主(Master)上:
mysql> show master status; //主机上查看最新的binlog日志名及pos点 从(Slave)机上:
mysql> stop slave; //从机停掉slave服务
mysql> change master to master_host='192.168.137.26', master_user='slave4', master_password='789', MASTER_LOG_FILE='主机最新binlog日志名', MASTER_LOG_POS=最新pos点;
mysql> start slave;
mysql> show slave status \G; 七、【实验】如果开始的环境不是主从架构,跑了一段时间主(Master)机已经有了数据,且主机的binlog日志已经不完整了,可由两种方案: 方案一(推荐):对主(Master)机做一次完整的mysqldump备份,拷贝到从(Slave)机执行从机恢复,然后从机再开启slave服务 A.【主机操作】备份主机数据(比如:test和zyyshop是需要以后同步的库)
# /usr/local/mysql/bin/mysqldump -uroot -p123456 -lF --log-error=/root/myDump.err -B test zyyshop > /root/test_zyyshop.sql B.【主机操作】立即查看一下主机的最新的binlog日志,并记录binlog日志名和pos点,从机就从这儿开始同步即可:
# /usr/local/mysql/bin/mysql -uroot -p123456
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000012 | 107 | | |
+------------------+----------+--------------+------------------+ C.【主机操作】将备份的文件直接恢复到远程的从(Slave)机数据库上:
方法1:先将 test_zyyshop.sql 备份文件 SCP 拷贝到远程从(Slave)机,再登录到远程从机恢复:
A.拷贝备份数据到从机:
# scp /root/test_zyyshop.sql root@192.168.137.27:/root/masterdb.sql
需要两台机器都安装scp才可,scp属于openssh-clients这个包,安装方法:# yum install -y openssh-clients B.[从机操作]将从机的备份数据恢复:
# /usr/local/mysql/bin/mysql -uroot -p123456 -v < /root/masterdb.sql 方法2:直接恢复到远程从(Slave)机上:
# /usr/local/mysql/bin/mysql -uroot -p123456 -h192.168.137.27 -v < /root/test_zyyshop.sql 至此从机已将主机的备份文件恢复到从机,接下来只要不断向主机同步binlog日志就OK了。 D.[从机操作] 在从(Slave)上执行命令,动态改变连接到主(Master)机的配置,生成或更新master.info文件:
# /usr/local/mysql/bin/mysql -uroot -p123456 mysql> change master to master_host='192.168.137.26', master_user='slave4', master_password='789', MASTER_LOG_FILE='mysql-bin.000012', MASTER_LOG_POS=107; mysql> start slave;
mysql> show slave status \G; *************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.137.26
Master_User: slave4
Master_Port: 3306
Connect_Retry: 10
Master_Log_File: mysql-bin.000012
Read_Master_Log_Pos: 107
Relay_Log_File: zzx-relay-bin.000002
Relay_Log_Pos: 253
Relay_Master_Log_File: mysql-bin.000012
Slave_IO_Running: Yes
Slave_SQL_Running: Yes ................ 小结:如果slave启动一切正常,就成功了! 方案二:打包主机的数据目录拷贝到从(Slave)机进行从机恢复,然后从机再开启slave服务
★ 注: 此法适用于MyISAM引擎表,不适用于Innodb引擎表。 # /usr/local/mysql/bin/mysql -uroot -p123456 A.【主机操作】对主(Master)机所有表进行“读锁”:
mysql> flush tables with read lock; 查看一下主机的最新的binlog日志,并记录binlog日志名和pos点,从机就从这儿开始同步即可:
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000012 | 107 | | |
+------------------+----------+--------------+------------------+ B.【主机操作】进入数据目录,打包需要的数据库包
# cd /usr/local/mysql/data/
# tar -zcvf test.tar.gz test
# tar -zcvf zyyshop.tar.gz zyyshop C.【主机操作】打包完成对主(Master)机所有表“解锁”:
mysql> unlock tables; D.【主机操作】将两数据库打包文件SCP到从(Slave)机的数据目录中:
# scp test.tar.gz zyyshop.tar.gz root@192.168.137.27:/usr/local/mysql/data/ E.[从机操作]进入数据存放目录,解压数据包(生成数据库):
# cd /usr/local/mysql/data/
# tar -zxvf test.tar.gz
# tar -zxvf zyyshop.tar.gz F.[从机操作] 在从(Slave)上执行命令(改变)连接主(Master)机,生成或更新master.info文件:
此步同上D步,略...... 八、主从复制中的几个重要文件
IO线程只负责从主(Master)机端复制 mysql-bin.00000x 日志,并把复制来的数据全部都放到 localhost-relay-bin.00000n 日志里。
SQL线程读取中继日志(relay-log.info)里的信息,将 localhost-relay-bin.00000n 日志里的数据写入本地从(Slave)机。 1.master.info 作用:
A.记录连接到主(Master)机的账号和密码;
B.记录复制到主(Master)机的哪个二进制文件和复制到二进制文件的位置(pos点); 2.relay-log.info 中继日志,作用:
A.记录了写了多少数据到本地从(Slave)机中; 附、show slave status\G 返回信息解析:
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event # IO的线程的状态
Master_Host: 192.168.137.26 # 链接主服务器的IP
Master_User: mark # 登录主服务器用户名
Master_Port: 3306 # 登录主服务器端口
Connect_Retry: 10 # 主从断开后,多少秒重新链接
Master_Log_File: mysql-bin.000004 # 从服务器I/O 线程当前读取的主服务器二进制日志文件的名字
Read_Master_Log_Pos: 190 # 从服务器I/O 线程从当前的主服务器二进制日志中读取的位置起点。
Relay_Log_File: ip_lb-relay-bin.000002 # 从服务器SQL 线程当前读取并执行的中继日志文件的名字
Relay_Log_Pos: 336 # 从服务器SQL 线程当前从中继日志中读取执行的位置起点。
Relay_Master_Log_File: mysql-bin.000004 # 从服务器中的SQL进程中正在执行的语句的位置
Slave_IO_Running: Yes # 从服务器的IO线程运行是否开启
Slave_SQL_Running: Yes # 从服务器的SQL线程运行是否开启
Replicate_Do_DB: # 主从需要复制的数据库名
Replicate_Ignore_DB: # 主从不需要复制的数据库名
Replicate_Do_Table: # 主从需要复制的表
Replicate_Ignore_Table: # 主从不需要复制的表
Replicate_Wild_Do_Table: # 可以跨库复制的表
Replicate_Wild_Ignore_Table: # 不能跨库复制的表
Last_Errno: 0 # 最后复制的错误号...0表示没有错误
Last_Error: # 最后复制的错误信息
Skip_Counter: 0 # 最近被使用的用于SQL_SLAVE_SKIP_COUNTER的值。(这个值表示跳过多少个事件在来执行SQL)
Exec_Master_Log_Pos: 190 # SQL线程执行到主服务器log-bin文件的位置.如果这个值与Read_Master_Log_Pos一样.则可以证明
Relay_Log_Space: 492 # 所有原有的中继日志结合起来的总大小。
Until_Condition: None # 在START SLAVE语句的UNTIL子句中指定的值
Until_Log_File: # 在START SLAVE语句的UNTIL子句中指定的值
Until_Log_Pos: 0 # 在START SLAVE语句的UNTIL子句中指定的值
Master_SSL_Allowed: No # 这些字段显示了被从属服务器使用的参数。这些参数用于连接主服务器。
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0 # 本字段是从属服务器“落后”多少的一个指示。当从属SQL线程正在运行时(处理更新),
本字段为在主服务器上由此线程执行的最近的一个事件的时间标记开始,已经过的秒数。
当此线程被从属服务器I/O线程赶上,并进入闲置状态,等待来自I/O线程的更多的事件时,本字段为零。
总之,本字段测量从属服务器SQL线程和从属服务器I/O线程之间的时间差距,单位以秒计。
如果主服务器和从属服务器之间的网络连接较快,则从属服务器I/O线程会非常接近主服务器,
所以本字段能够十分近似地指示,从属服务器SQL线程比主服务器落后多少。
如果网络较慢,则这种指示不准确;从属SQL线程经常会赶上读取速度较慢地从属服务器I/O线程,
因此,Seconds_Behind_Master经常显示值为0。即使I/O线程落后于主服务器时,也是如此。
换句话说,本列只对速度快的网络有用。
即使主机和从机不具有相同的时钟,时间差计算也会起作用(当从属服务器I/O线程启动时,计算
时间差。并假定从此时以后,时间差保持不变)。
如果从属SQL线程不运行,或者如果从属服务器I/O线程不运行或未与主服务器连接,
则Seconds_Behind_Master为NULL(意义为“未知”)。
举例说明,如果在重新连接之前,从属服务器I/O线程休眠了master-connect-retry秒,则显示NULL,
因为从属服务器不知道主服务器正在做什么,也不能有把握地说落后多少。
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
1 row in set (0.00 sec) 参考文档: MySQL5.5 主从复制
http://blog.csdn.net/m582445672/article/details/7731565 mysql5.5 主从复制 (触发器,函数,存储引擎,事件处理)说明
http://blog.csdn.net/m582445672/article/details/7670802 Mysql主从复制[生产环境]
http://wenku.baidu.com/link?url=a-SLn41EKYseSxikYViSqvf9IBwGh7d0NsaKPnBbZjc3sED4VF_NfpjMT5IrUhC3yeuq75geJuglzrz2RXmY41t3mVHcx9-oaNIAG6dRuIu Slave_SQL_Running: No mysql同步故障解决方法
http://kerry.blog.51cto.com/172631/277414/

MySQL 5.5 主从复制的更多相关文章

  1. MySQL数据的主从复制、半同步复制和主主复制详解

    一.MySQL复制概述 ⑴.MySQL数据的复制的基本介绍 目前MySQL数据库已经占去数据库市场上很大的份额,其一是由于MySQL数据的开源性和高性能,当然还有重要的一条就是免费~不过不知道还能免费 ...

  2. MySQL数据的主从复制、半同步复制和主主复制详解-转

    一.MySQL复制概述 ⑴.MySQL数据的复制的基本介绍 目前MySQL数据库已经占去数据库市场上很大的份额,其一是由于MySQL数据的开源性和高性能,当然还有重要的一条就是免费~不过不知道还能免费 ...

  3. Mysql的ssl主从复制+半同步主从复制

    Mysql的ssl主从复制+半同步主从复制 准备工作 1.主从服务器时间同步 [root@localhost ~]# crontab -e */30 * * * * /usr/sbin/ntpdate ...

  4. Mysql高级之主从复制

    原文:Mysql高级之主从复制 主从复制不就是多台服务器嘛!,一个改变另一个也改变啦,内容其实都一样! 原理: 对数据库进行操作会生成一个文件,binlog(二进制文件),从服务器配置relaylog ...

  5. 003.MySQL高可用主从复制新增slave

    一 基础环境 主机名 系统版本 MySQL版本 主机IP master CentOS 6.8 MySQL 5.6 172.24.8.10 slave01 CentOS 6.8 MySQL 5.6 17 ...

  6. MySQL 5.7主从复制从零开始设置及全面详解——实现多线程并行同步,解决主从复制延迟问题!

    MySQL 5.7主从复制从零开始设置及全面详解——实现多线程并行同步,解决主从复制延迟问题!2017年06月15日 19:59:44 蓝色-鸢尾 阅读数:2062版权声明:本文为博主原创文章,如需转 ...

  7. 高可用Mysql架构_Mysql主从复制、Mysql双主热备、Mysql双主双从、Mysql读写分离(Mycat中间件)、Mysql分库分表架构(Mycat中间件)的演变

    [Mysql主从复制]解决的问题数据分布:比如一共150台机器,分别往电信.网通.移动各放50台,这样无论在哪个网络访问都很快.其次按照地域,比如国内国外,北方南方,这样地域性访问解决了.负载均衡:M ...

  8. 为什么mysql要做主从复制?

    为什么MySQL要做主从复制(读写分离)? 通俗来讲,如果对数据库的读和写都在同一个数据库服务器中操作,业务系统性能会降低. 为了提升业务系统性能,优化用户体验,可以通过做主从复制(读写分离)来减轻主 ...

  9. maria(mysql)的主从复制

    一.mariadb的基本操作 1.远程连接 mysql -uroot -p -h 127.0.0.1 mysql -uroot -p -h 192.168.226.128 2.赋予远程连接的权限 gr ...

随机推荐

  1. (三)Hololens Unity 开发之 语音识别

    学习源于官方文档 Voice input in Unity 笔记一部分是直接翻译官方文档,部分各人理解不一致的和一些比较浅显的保留英文原文 (三)Hololens Unity 开发之 语音识别 Hol ...

  2. stl源码分析之list

    本文主要分析gcc4.8版本的stl list的源码实现,与vector的线性空间结构不同,list的节点是任意分散的,节点之间通过指针连接,好处是在任何位置插入删除元素都只需要常数时间,缺点是不能随 ...

  3. Charles连接苹果及JSON乱码情况解决

    1.  Charles的JSON乱码情况解决: 点击Charles界面上的help—SSL proxying—install Charles Root Certificate,将证书安装到[受信任的根 ...

  4. Springboot 配置实现定时任务

    善于思考,拥抱变化,才能拥有未来 在springboot项目中可以通过配置文件来实现定时任务的轮询,当然也可以将具体执行的corn表达式配置到数据库,实现动态从数据库获取. @Configuratio ...

  5. vsftpd安装配置虚拟用户

    原文发表于cu:2016-03-11 参考文档: FTP原理:http://vbird.dic.ksu.edu.tw/linux_server/0410vsftpd_1.php FTP配置:http: ...

  6. linux下各文件夹的结构说明及用途介绍(转载)

    详细介绍文档 转载文章路径 /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录的基点,比如用户 ...

  7. 支持向量机SVM 初识

    虽然已经学习了神经网络和深度学习并在几个项目之中加以运用了,但在斯坦福公开课上听吴恩达老师说他(在当时)更喜欢使用SVM,而很少使用神经网络来解决问题,因此来学习一下SVM的种种. 先解释一些概念吧: ...

  8. [leetcode-908-Smallest Range I]

    Given an array A of integers, for each integer A[i] we may choose any x with -K <= x <= K, and ...

  9. LCA最近公共祖先(Tarjan离线算法)

    这篇博客对Tarjan算法的原理和过程模拟的很详细. 转载大佬的博客https://www.cnblogs.com/JVxie/p/4854719.html 第二次更新,之前转载的博客虽然胜在详细,但 ...

  10. ACM ICPC 2016–2017, NEERC, Northern Subregional Contest Problem J. Java2016

    题目来源:http://codeforces.com/group/aUVPeyEnI2/contest/229510 时间限制:2s 空间限制:256MB 题目大意: 给定一个数字c 用 " ...