show master/slave status求根溯源
show master/slave status分别是查看主数据库以及副数据库的状态,是一种能查看主从复制运行情况的方式。
这里仅仅讨论linux下的nysql5.7.13版本的执行情况
一、show master status
开始与show global status类似,都是分配一个线程去处理该连接的命令(图1)
图1 show master status命令处理流程
1.在sql_yacc.cc:yyparse中
、
(1)初始化内存
(2)初始化解析后命令选项 SQLCOM_SHOW_MASTER_STAT
(3)初始化为单查询(此处无用)
2.show master status命令处理流程
图2. show_master_status的处理流程
(1)在mysql_execute_command(图2#3)中
进入该选项分支
case SQLCOM_SHOW_MASTER_STAT:
{
/* Accept one of two privileges */
if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
res = show_master_status(thd);
break;
}
(2)在show_master_status(图2#2)中
1)初始化发送格式格式
field_list.push_back(new Item_empty_string("File", FN_REFLEN));
field_list.push_back(new Item_return_int("Position",,
MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Binlog_Do_DB",));
field_list.push_back(new Item_empty_string("Binlog_Ignore_DB",));
field_list.push_back(new Item_empty_string("Executed_Gtid_Set",
gtid_set_size)); if (thd->send_result_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
2)储存内容并发送
protocol->start_row(); if (mysql_bin_log.is_open())
{
LOG_INFO li;
mysql_bin_log.get_current_log(&li);
size_t dir_len = dirname_length(li.log_file_name);
protocol->store(li.log_file_name + dir_len, &my_charset_bin);
protocol->store((ulonglong) li.pos);
store(protocol, binlog_filter->get_do_db());
store(protocol, binlog_filter->get_ignore_db());
protocol->store(gtid_set_buffer, &my_charset_bin);
if (protocol->end_row())
{
my_free(gtid_set_buffer);
DBUG_RETURN(true);
}
}
(3)在raw_get_current_log(图2#1)中
int MYSQL_BIN_LOG::get_current_log(LOG_INFO* linfo, bool need_lock_log/*true*/)
{
if (need_lock_log)
mysql_mutex_lock(&LOCK_log);
int ret = raw_get_current_log(linfo);
if (need_lock_log)
mysql_mutex_unlock(&LOCK_log);
return ret;
}
主要的处理函数就是raw_get_current_log
(4)在raw_get_current_log(图2#0)中
在binlog的那点事中的写位置定位有详细解释,这里不再赘述。
二、show slave status
图3 show slave status命令处理流程
1.在sql_yacc.cc:yyparse中
1)初始化信息
2)初始化信道
3)初始化执行命令类型
4)使用单查询(此处无用)
2.命令执行流程
图4 show slave status命令处理
(1)同样地在mysql_execute_command(图4#3)中
case SQLCOM_SHOW_MASTER_STAT:
{
/* Accept one of two privileges */
if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
res = show_master_status(thd);
break;
}
(2)在show_master_status(图4#2)中
由于在解析中看到lex->mi.for_channel=false,为此进入此分支
if (!lex->mi.for_channel)
res= show_slave_status(thd);
(3)在show_master_status(图4#3)中
1)清空每一信道的内存
for (mi_map::iterator it= channel_map.begin(); it!=channel_map.end(); it++)
{
mi= it->second;
/*
The following statement is needed because, when mi->host[0]=0
we don't alloc memory for retried_gtid_set. However, we try
to free it at the end, causing a crash. To be on safeside,
we initialize it to NULL, so that my_free() takes care of it.
*/
io_gtid_set_buffer_array[idx]= NULL; if (mi != NULL && mi->host[])
{
const Gtid_set* io_gtid_set= mi->rli->get_gtid_set(); /*
@todo: a single memory allocation improves speed,
instead of doing it for each loop
*/ if ((io_gtid_set_size=
io_gtid_set->to_string(&io_gtid_set_buffer_array[idx])) < )
{
my_eof(thd);
my_free(sql_gtid_set_buffer); for (uint i= ; i < idx -; i++)
{
my_free(io_gtid_set_buffer_array[i]);
}
my_free(io_gtid_set_buffer_array); global_sid_lock->unlock();
DBUG_RETURN(true);
}
else
max_io_gtid_set_size= max_io_gtid_set_size > io_gtid_set_size ?
max_io_gtid_set_size : io_gtid_set_size;
}
idx++;
}
2)在show_slave_status_metadata,申请内存
void show_slave_status_metadata(List<Item> &field_list,
int io_gtid_set_size, int sql_gtid_set_size)
{ field_list.push_back(new Item_empty_string("Slave_IO_State", ));
field_list.push_back(new Item_empty_string("Master_Host",
HOSTNAME_LENGTH+));
field_list.push_back(new Item_empty_string("Master_User",
USERNAME_LENGTH+));
field_list.push_back(new Item_return_int("Master_Port", ,MYSQL_TYPE_LONG));
field_list.push_back(new Item_return_int("Connect_Retry", ,
MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Master_Log_File", FN_REFLEN));
field_list.push_back(new Item_return_int("Read_Master_Log_Pos", ,
MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Relay_Log_File", FN_REFLEN));
field_list.push_back(new Item_return_int("Relay_Log_Pos", ,
MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Relay_Master_Log_File",
FN_REFLEN));
field_list.push_back(new Item_empty_string("Slave_IO_Running", ));
field_list.push_back(new Item_empty_string("Slave_SQL_Running", ));
field_list.push_back(new Item_empty_string("Replicate_Do_DB", ));
field_list.push_back(new Item_empty_string("Replicate_Ignore_DB", ));
field_list.push_back(new Item_empty_string("Replicate_Do_Table", ));
field_list.push_back(new Item_empty_string("Replicate_Ignore_Table", ));
field_list.push_back(new Item_empty_string("Replicate_Wild_Do_Table", ));
field_list.push_back(new Item_empty_string("Replicate_Wild_Ignore_Table",
));
field_list.push_back(new Item_return_int("Last_Errno", , MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Last_Error", ));
field_list.push_back(new Item_return_int("Skip_Counter", ,
MYSQL_TYPE_LONG));
field_list.push_back(new Item_return_int("Exec_Master_Log_Pos", ,
MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_return_int("Relay_Log_Space", ,
MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Until_Condition", ));
field_list.push_back(new Item_empty_string("Until_Log_File", FN_REFLEN));
field_list.push_back(new Item_return_int("Until_Log_Pos", ,
MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Master_SSL_Allowed", ));
field_list.push_back(new Item_empty_string("Master_SSL_CA_File", FN_REFLEN));
field_list.push_back(new Item_empty_string("Master_SSL_CA_Path", FN_REFLEN));
field_list.push_back(new Item_empty_string("Master_SSL_Cert", FN_REFLEN));
field_list.push_back(new Item_empty_string("Master_SSL_Cipher", FN_REFLEN));
field_list.push_back(new Item_empty_string("Master_SSL_Key", FN_REFLEN));
field_list.push_back(new Item_return_int("Seconds_Behind_Master", ,
MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Master_SSL_Verify_Server_Cert",
));
field_list.push_back(new Item_return_int("Last_IO_Errno", , MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Last_IO_Error", ));
field_list.push_back(new Item_return_int("Last_SQL_Errno", , MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Last_SQL_Error", ));
field_list.push_back(new Item_empty_string("Replicate_Ignore_Server_Ids",
FN_REFLEN));
field_list.push_back(new Item_return_int("Master_Server_Id", sizeof(ulong),
MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Master_UUID", UUID_LENGTH));
field_list.push_back(new Item_empty_string("Master_Info_File",
* FN_REFLEN));
field_list.push_back(new Item_return_int("SQL_Delay", , MYSQL_TYPE_LONG));
field_list.push_back(new Item_return_int("SQL_Remaining_Delay", , MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Slave_SQL_Running_State", ));
field_list.push_back(new Item_return_int("Master_Retry_Count", ,
MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Master_Bind", HOSTNAME_LENGTH+));
field_list.push_back(new Item_empty_string("Last_IO_Error_Timestamp", ));
field_list.push_back(new Item_empty_string("Last_SQL_Error_Timestamp", ));
field_list.push_back(new Item_empty_string("Master_SSL_Crl", FN_REFLEN));
field_list.push_back(new Item_empty_string("Master_SSL_Crlpath", FN_REFLEN));
field_list.push_back(new Item_empty_string("Retrieved_Gtid_Set",
io_gtid_set_size));
field_list.push_back(new Item_empty_string("Executed_Gtid_Set",
sql_gtid_set_size));
field_list.push_back(new Item_return_int("Auto_Position", sizeof(ulong),
MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Replicate_Rewrite_DB", ));
field_list.push_back(new Item_empty_string("Channel_Name", CHANNEL_NAME_LENGTH));
field_list.push_back(new Item_empty_string("Master_TLS_Version", FN_REFLEN)); }
3)初始化发送协议
if (thd->send_result_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
{
goto err;
}
4)向各个信道发送要查询的状态
idx=;
for (mi_map::iterator it= channel_map.begin(); it!=channel_map.end(); it++)
{
mi= it->second; if (mi != NULL && mi->host[])
{
if (show_slave_status_send_data(thd, mi, io_gtid_set_buffer_array[idx],
sql_gtid_set_buffer))
goto err; if (protocol->end_row())
goto err;
}
idx++;
}
对于show_slave_status_send_data
bool show_slave_status_send_data(THD *thd, Master_info *mi,
char* io_gtid_set_buffer,
char* sql_gtid_set_buffer)
{
DBUG_ENTER("show_slave_status_send_data"); Protocol *protocol = thd->get_protocol();
char* slave_sql_running_state= NULL; DBUG_PRINT("info",("host is set: '%s'", mi->host)); protocol->start_row(); /*
slave_running can be accessed without run_lock but not other
non-volatile members like mi->info_thd or rli->info_thd, for
them either info_thd_lock or run_lock hold is required.
*/
mysql_mutex_lock(&mi->info_thd_lock);
protocol->store(mi->info_thd ? mi->info_thd->get_proc_info() : "",
&my_charset_bin);
mysql_mutex_unlock(&mi->info_thd_lock); mysql_mutex_lock(&mi->rli->info_thd_lock);
slave_sql_running_state= const_cast<char *>(mi->rli->info_thd ? mi->rli->info_thd->get_proc_info() : "");
mysql_mutex_unlock(&mi->rli->info_thd_lock); mysql_mutex_lock(&mi->data_lock);
mysql_mutex_lock(&mi->rli->data_lock);
mysql_mutex_lock(&mi->err_lock);
mysql_mutex_lock(&mi->rli->err_lock); DEBUG_SYNC(thd, "wait_after_lock_active_mi_and_rli_data_lock_is_acquired");
protocol->store(mi->host, &my_charset_bin);
protocol->store(mi->get_user(), &my_charset_bin);
protocol->store((uint32) mi->port);
protocol->store((uint32) mi->connect_retry);
protocol->store(mi->get_master_log_name(), &my_charset_bin);
protocol->store((ulonglong) mi->get_master_log_pos());
protocol->store(mi->rli->get_group_relay_log_name() +
dirname_length(mi->rli->get_group_relay_log_name()),
&my_charset_bin);
protocol->store((ulonglong) mi->rli->get_group_relay_log_pos());
protocol->store(mi->rli->get_group_master_log_name(), &my_charset_bin);
protocol->store(mi->slave_running == MYSQL_SLAVE_RUN_CONNECT ?
"Yes" : (mi->slave_running == MYSQL_SLAVE_RUN_NOT_CONNECT ?
"Connecting" : "No"), &my_charset_bin);
protocol->store(mi->rli->slave_running ? "Yes":"No", &my_charset_bin);
store(protocol, rpl_filter->get_do_db());
store(protocol, rpl_filter->get_ignore_db()); char buf[];
String tmp(buf, sizeof(buf), &my_charset_bin);
rpl_filter->get_do_table(&tmp);
protocol->store(&tmp);
rpl_filter->get_ignore_table(&tmp);
protocol->store(&tmp);
rpl_filter->get_wild_do_table(&tmp);
protocol->store(&tmp);
rpl_filter->get_wild_ignore_table(&tmp);
protocol->store(&tmp); protocol->store(mi->rli->last_error().number);
protocol->store(mi->rli->last_error().message, &my_charset_bin);
protocol->store((uint32) mi->rli->slave_skip_counter);
protocol->store((ulonglong) mi->rli->get_group_master_log_pos());
protocol->store((ulonglong) mi->rli->log_space_total); const char *until_type= ""; switch (mi->rli->until_condition)
{
case Relay_log_info::UNTIL_NONE:
until_type= "None";
break;
case Relay_log_info::UNTIL_MASTER_POS:
until_type= "Master";
break;
case Relay_log_info::UNTIL_RELAY_POS:
until_type= "Relay";
break;
case Relay_log_info::UNTIL_SQL_BEFORE_GTIDS:
until_type= "SQL_BEFORE_GTIDS";
break;
case Relay_log_info::UNTIL_SQL_AFTER_GTIDS:
until_type= "SQL_AFTER_GTIDS";
break;
case Relay_log_info::UNTIL_SQL_VIEW_ID:
until_type= "SQL_VIEW_ID";
break;
case Relay_log_info::UNTIL_SQL_AFTER_MTS_GAPS:
until_type= "SQL_AFTER_MTS_GAPS";
case Relay_log_info::UNTIL_DONE:
until_type= "DONE";
break;
default:
DBUG_ASSERT();
}
protocol->store(until_type, &my_charset_bin);
protocol->store(mi->rli->until_log_name, &my_charset_bin);
protocol->store((ulonglong) mi->rli->until_log_pos); #ifdef HAVE_OPENSSL
protocol->store(mi->ssl? "Yes":"No", &my_charset_bin);
#else
protocol->store(mi->ssl? "Ignored":"No", &my_charset_bin);
#endif
protocol->store(mi->ssl_ca, &my_charset_bin);
protocol->store(mi->ssl_capath, &my_charset_bin);
protocol->store(mi->ssl_cert, &my_charset_bin);
protocol->store(mi->ssl_cipher, &my_charset_bin);
protocol->store(mi->ssl_key, &my_charset_bin); /*
The pseudo code to compute Seconds_Behind_Master:
if (SQL thread is running)
{
if (SQL thread processed all the available relay log)
{
if (IO thread is running)
print 0;
else
print NULL;
}
else
compute Seconds_Behind_Master;
}
else
print NULL;
*/ if (mi->rli->slave_running)
{
/*
Check if SQL thread is at the end of relay log
Checking should be done using two conditions
condition1: compare the log positions and
condition2: compare the file names (to handle rotation case)
*/
if ((mi->get_master_log_pos() == mi->rli->get_group_master_log_pos()) &&
(!strcmp(mi->get_master_log_name(), mi->rli->get_group_master_log_name())))
{
if (mi->slave_running == MYSQL_SLAVE_RUN_CONNECT)
protocol->store(0LL);
else
protocol->store_null();
}
else
{
long time_diff= ((long)(time() - mi->rli->last_master_timestamp)
- mi->clock_diff_with_master);
/*
Apparently on some systems time_diff can be <0. Here are possible
reasons related to MySQL:
- the master is itself a slave of another master whose time is ahead.
- somebody used an explicit SET TIMESTAMP on the master.
Possible reason related to granularity-to-second of time functions
(nothing to do with MySQL), which can explain a value of -1:
assume the master's and slave's time are perfectly synchronized, and
that at slave's connection time, when the master's timestamp is read,
it is at the very end of second 1, and (a very short time later) when
the slave's timestamp is read it is at the very beginning of second
2. Then the recorded value for master is 1 and the recorded value for
slave is 2. At SHOW SLAVE STATUS time, assume that the difference
between timestamp of slave and rli->last_master_timestamp is 0
(i.e. they are in the same second), then we get 0-(2-1)=-1 as a result.
This confuses users, so we don't go below 0: hence the max(). last_master_timestamp == 0 (an "impossible" timestamp 1970) is a
special marker to say "consider we have caught up".
*/
protocol->store((longlong)(mi->rli->last_master_timestamp ?
max(0L, time_diff) : ));
}
}
else
{
protocol->store_null();
}
protocol->store(mi->ssl_verify_server_cert? "Yes":"No", &my_charset_bin); // Last_IO_Errno
protocol->store(mi->last_error().number);
// Last_IO_Error
protocol->store(mi->last_error().message, &my_charset_bin);
// Last_SQL_Errno
protocol->store(mi->rli->last_error().number);
// Last_SQL_Error
protocol->store(mi->rli->last_error().message, &my_charset_bin);
// Replicate_Ignore_Server_Ids
{
char buff[FN_REFLEN];
ulong i, cur_len;
for (i= , buff[]= , cur_len= ;
i < mi->ignore_server_ids->dynamic_ids.size(); i++)
{
ulong s_id, slen;
char sbuff[FN_REFLEN];
s_id= mi->ignore_server_ids->dynamic_ids[i];
slen= sprintf(sbuff, (i == ? "%lu" : ", %lu"), s_id);
if (cur_len + slen + > FN_REFLEN)
{
/*
break the loop whenever remained space could not fit
ellipses on the next cycle
*/
sprintf(buff + cur_len, "...");
break;
}
cur_len += sprintf(buff + cur_len, "%s", sbuff);
}
protocol->store(buff, &my_charset_bin);
}
// Master_Server_id
protocol->store((uint32) mi->master_id);
protocol->store(mi->master_uuid, &my_charset_bin);
// Master_Info_File
protocol->store(mi->get_description_info(), &my_charset_bin);
// SQL_Delay
protocol->store((uint32) mi->rli->get_sql_delay());
// SQL_Remaining_Delay
if (slave_sql_running_state == stage_sql_thd_waiting_until_delay.m_name)
{
time_t t= my_time(), sql_delay_end= mi->rli->get_sql_delay_end();
protocol->store((uint32)(t < sql_delay_end ? sql_delay_end - t : ));
}
else
protocol->store_null();
// Slave_SQL_Running_State
protocol->store(slave_sql_running_state, &my_charset_bin);
// Master_Retry_Count
protocol->store((ulonglong) mi->retry_count);
// Master_Bind
protocol->store(mi->bind_addr, &my_charset_bin);
// Last_IO_Error_Timestamp
protocol->store(mi->last_error().timestamp, &my_charset_bin);
// Last_SQL_Error_Timestamp
protocol->store(mi->rli->last_error().timestamp, &my_charset_bin);
// Master_Ssl_Crl
protocol->store(mi->ssl_crl, &my_charset_bin);
// Master_Ssl_Crlpath
protocol->store(mi->ssl_crlpath, &my_charset_bin);
// Retrieved_Gtid_Set
protocol->store(io_gtid_set_buffer, &my_charset_bin);
// Executed_Gtid_Set
protocol->store(sql_gtid_set_buffer, &my_charset_bin);
// Auto_Position
protocol->store(mi->is_auto_position() ? : );
// Replicate_Rewrite_DB
rpl_filter->get_rewrite_db(&tmp);
protocol->store(&tmp);
// channel_name
protocol->store(mi->get_channel(), &my_charset_bin);
// Master_TLS_Version
protocol->store(mi->tls_version, &my_charset_bin); mysql_mutex_unlock(&mi->rli->err_lock);
mysql_mutex_unlock(&mi->err_lock);
mysql_mutex_unlock(&mi->rli->data_lock);
mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(false);
}
在这个函数和show_slave_status_metadata中,我们可以看到每个状态取自那个函数,这样就可以弄明白每个状态的实时更新性
在这里我们关注的是Master_Log_File和 Read_Master_Log_Pos的状态。这是主从同步情况最主要的状态,但是这涉及到slave IO的运行情况,我们下次在slave IO说明
show master/slave status求根溯源的更多相关文章
- Mysql命令show global status求根溯源
近来,发现好多公司对mysql的性能监控是通过show global status实现的,因此对于这个命令想要探究一番,看他是否是实时更新的. 在此之前,我们必须搞明白mysql对于这个命令的执行过程 ...
- MySQL show master / slave status 命令参数
一.show master status 二.show slave status Slave_IO_State SHOW PROCESSLIST输出的State字段的拷贝.SHOW PROCESSLI ...
- 两主机搭建MySQL主从复制后,show slave status显示:Last_IO_Error: error connecting to master ……
两台主机A.B搭建mysql主从复制关系(A为master,B为slave)后,在slave上执行show slave status,结果中显示Last_IO_Error: error connect ...
- [置顶] 两主机搭建MySQL主从复制后,show slave status显示:Last_IO_Error: error connecting to master ……
两台主机A.B搭建mysql主从复制关系(A为master,B为slave)后,在slave上执行show slave status,结果中显示Last_IO_Error: error connect ...
- show master status, show slave status中的Executed_Gtid_Set
slave 如果server是slave节点,在server上执行show master staus与show slave status显示的Executed_Gtid_Set是一样的. slave也 ...
- 在阿里云Centos7.6上面配置Mysql主从数据库(master/slave),实现读写分离
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_85 在之前的一篇文章中,阐述了如何在高并发高负载的场景下使用nginx做后台服务的负载均衡:在阿里云Centos上配置nginx+ ...
- Windows下搭建MySQL Master Slave
一.背景 服务器上放了很多MySQL数据库,为了安全,现在需要做Master/Slave方案,因为操作系统是Window的,所以没有办法使用keepalived这个HA工具,但是我们可以接受人工进行切 ...
- mysql (master/slave)复制原理及配置
1 复制概述 Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重 ...
- show slave status中的log_file / log_pos
在MySQL的master-slave或dual master的架构中,我们经常使用show slave status命令来查看复制状态. 这里涉及几个重要的日志文件和位置: Master_Log_F ...
随机推荐
- css箭头
.aui-list-item-arrow:before { content: ''; width: 0.4rem; height: 0.4rem; position: absolute; top: 5 ...
- 转:Webpack 指南(整理 草稿)
基础 安装 首先要安装 Node.js, Node.js 自带了软件包管理器 npm.用 npm 全局安装 Webpack: $ npm install webpack -g 通常我们会将 Webpa ...
- MongoDB实现分页(两种方法)
1.插入实验数据 偷懒用下samus,100条. ; i < ; i++) { Document doc = new Document(); doc["ID"] = i; d ...
- linux下QT程序输出乱码解决方法
参考文章:http://blog.csdn.net/jiang1013nan/article/details/6667871 http://my.oschina.net/zjlaobusi/blog/ ...
- 让/etc/profile文件修改后立即生效
方法1: 让/etc/profile文件修改后立即生效 ,可以使用如下命令: # . /etc/profile 注意: . 和 /etc/profile 有空格 方法2: 让/etc/profile ...
- *CF2.D(哥德巴赫猜想)
D. Taxes time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...
- Red Hat5.5 install Generic mysql-5.7.10
1.确认以下依赖包已安装 [ncurses ncurses-devel openssl-devel bison autoconf automake bison gcc m4 libtool make ...
- WebService的一些案例
既然要实现WebService,首先先来创建一个Service类 package cn.happy.webservice; import javax.jws.WebService; import ja ...
- 一鼓作气 博客--第二篇 note2
1.循环正常结束是指没有中间截断,即没有执行break; for i in range(10) print(i) else: print("循环正常结束") 2.嵌套循环 for ...
- eclipse 中的注释 快捷键
(1)Ctrl+Space 说明:内容助理.提供对方法,变量,参数,javadoc等得提示, 应运在多种场合,总之需要提示的时候可先按此快捷键. 注:避免输入法的切换设置与此设置冲突 (2)Ctrl ...