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求根溯源的更多相关文章

  1. Mysql命令show global status求根溯源

    近来,发现好多公司对mysql的性能监控是通过show global status实现的,因此对于这个命令想要探究一番,看他是否是实时更新的. 在此之前,我们必须搞明白mysql对于这个命令的执行过程 ...

  2. MySQL show master / slave status 命令参数

    一.show master status 二.show slave status Slave_IO_State SHOW PROCESSLIST输出的State字段的拷贝.SHOW PROCESSLI ...

  3. 两主机搭建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 ...

  4. [置顶] 两主机搭建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 ...

  5. show master status, show slave status中的Executed_Gtid_Set

    slave 如果server是slave节点,在server上执行show master staus与show slave status显示的Executed_Gtid_Set是一样的. slave也 ...

  6. 在阿里云Centos7.6上面配置Mysql主从数据库(master/slave),实现读写分离

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_85 在之前的一篇文章中,阐述了如何在高并发高负载的场景下使用nginx做后台服务的负载均衡:在阿里云Centos上配置nginx+ ...

  7. Windows下搭建MySQL Master Slave

    一.背景 服务器上放了很多MySQL数据库,为了安全,现在需要做Master/Slave方案,因为操作系统是Window的,所以没有办法使用keepalived这个HA工具,但是我们可以接受人工进行切 ...

  8. mysql (master/slave)复制原理及配置

    1 复制概述 Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重 ...

  9. show slave status中的log_file / log_pos

    在MySQL的master-slave或dual master的架构中,我们经常使用show slave status命令来查看复制状态. 这里涉及几个重要的日志文件和位置: Master_Log_F ...

随机推荐

  1. 树链剖分+线段树 CF 593D Happy Tree Party(快乐树聚会)

    题目链接 题意: 有n个点的一棵树,两种操作: 1. a到b的路径上,给一个y,对于路径上每一条边,进行操作,问最后的y: 2. 修改某个条边p的值为c 思路: 链上操作的问题,想树链剖分和LCT,对 ...

  2. Codeforces CF#628 Education 8 C. Bear and String Distance

    C. Bear and String Distance time limit per test 1 second memory limit per test 256 megabytes input s ...

  3. [R语言]R语言计算unix timestamp的坑

    R+mongo的组合真是各种坑等着踩 由于mongo中的时间戳普遍使用的是unix timestamp的格式,因此需要对每天的数据进行计算的时候,很容易就想到对timestamp + gap对方式来实 ...

  4. DataTable转换为JSON数组

    最后的格式为:[{},{},...] StringBuilder DataTableToJSON(DataTable dt) { string columnName; StringBuilder bu ...

  5. overflow:hidden清除浮动原理

    overflow:hidden的意思是超出部分去掉,如果父元素height为auto,内部元素浮动,势必会将内部元素全部隐藏,故计算出内部浮动高度顺便清除浮动.

  6. ubuntu的vim模式

    之前想修改一个文件的内容,居然发现之前的东西又随着时间在空气中淡忘了,所以取了网上的一些摘文. 1.vim #在命令行中输入vim,进入vim编辑器 2. i #按一下i键,下端显示 --INSERT ...

  7. 第一天---HTML基础学习

    HTML(hyper text markup language) HTML不是一种编程语言,而是一种标记语言(markup language),标记语言是一套markup tag(标记标签),HTML ...

  8. web应用程序

    1.web应用程序和网站的区别 应用程序有两种模式C/S.B/S.C/S是客户端/服务器端程序,也就是说这类程序一般独立运行.而B/S就是浏览器端/服务器端应用程序,这类应用程序一般借助IE等浏览器来 ...

  9. 理解MVC,MVP和MVVM设计模式

    有3个非常受欢迎的MV-*系列设计模式:MVC,MVP,MVVM.他们被广泛应用于不多种结束.这篇文章我回阐述我自己对这3个设计模式的看法. MVC模式: MVC即Model-VIew-Control ...

  10. CentOS6.5安装中文输入法

    首先进入命令形式的客户端 切换成root用户,输入命令"su root"即可,接着输入 yum install "@Chinese Support" 命令按en ...