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. sql查询中datetime显示的格式为yyyy-DD-mm

    datetime数据库中保存的形式为2008/9/29 星期一 上午 12:00:00,希望界面显示2008-09-29,则可以用到以下sql语句. ),kgrq, ),),jhjgrq, ),'/' ...

  2. LeetCode 258. Add Digits

    Problem: Given a non-negative integer num, repeatedly add all its digits until the result has only o ...

  3. js模拟抛出球运动

    js练手之模拟水平抛球运动 -匀加速运动 -匀减速运动 模拟运动有些基本的思路,当前所在点的坐标,元素的长宽是多少,向右/向下运动x/y增加,向上/向左运动x/y减少,运动的路程是多少,用什么方程进行 ...

  4. spring源码解析——spring源码导入eclipse

    一.前言     众所周知,spring的强大之处.几乎所有的企业级开发中,都使用了spring了.在日常的开发中,我们是否只知道spring的配置,以及简单的使用场景.对其实现的代码没有进行深入的了 ...

  5. Cordova 3.x入门 - 目录

    这个系列是基于Cordova 3.x的,很多Android的东西都是Eclipse ADT+Ant的,而目前Android的开发已经完全切换到了Android Studio+Gradle,需要大家特别 ...

  6. 洛谷 P1466 集合 Subset Sums Label:DP

    题目描述 对于从1到N (1 <= N <= 39) 的连续整数集合,能划分成两个子集合,且保证每个集合的数字和是相等的.举个例子,如果N=3,对于{1,2,3}能划分成两个子集合,每个子 ...

  7. my97DatePicker日期控件——日期输入框联动,使用focus使第二个输入框没展示出日期控件

    描述问题场景: 1.jquery使用的版本是jquery-1.7.2.min.js 2.代码不是写在页面上的,是通过事件后追加的 <!DOCTYPE html> <html> ...

  8. Jquery垂直下拉二级菜单

    自己做了一个基于Jquery 的垂直下拉二级菜单功能,直接看图: Html的代码如下: <!DOCTYPE html> <html> <head> <meta ...

  9. 设计模式(十三) 职责链(chain of responsibility)

    软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径.设计模式中运用了面向对象编程语言的重要特性:封装.继承.多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累.最 ...

  10. <十四>JDBC_c3p0数据库连接池

    配置文件:c3p0-config.xml <!-- Hibernate官方推荐使用的数据库连接池即c3p0;dbcp是Tomcat在数据源中使用 --><c3p0-config> ...