mysql gtid 还是pxc_记一次 PXC 集群拆分引发的思考

原标题:记一次 PXC 集群拆分引发的思考

40960459b1ceef3100917826b66cb21b.png

作者简介

冷正磊

2018年2月加入去哪儿网 DBA 团队,主要负责机票业务的 MySQL 和 Redis 数据库的运维管理工作,以及数据库自动化运维平台部分功能的开发工作,对数据库技术具有浓厚兴趣,具有多年 MySQL 和 Redis 运维管理和性能优化经验。

1. 内容摘要

众所周知,MySQL 基于 GTID 复制功能的出现,极大地简化了 MySQL 复制拓扑初始化配置和变更以及高可用的切换。在去哪儿网,我们大量使用 PXC(Percona XtraDB Cluster)集群,然而 PXC 中用于记录事务的 Galera GTID 与普通的 MySQL GTID 还是有一点差异,运维过程中如果不加注意,可能会引发一些问题。本文通过记录一次 PXC 集群拆分的过程中由于未深刻理解这两者的差别而导致的问题与原因分析,总结了 Galera GTID 与 MySQL GTID 的异同点以及运维过程中应该注意的事项。

2. 背景

Qunar 机票核心业务某个 PXC 集群 C1 由于运行时间比较久,随着业务的持续发展,集群单个节点的实例数据大小已达到 5T 以上,对数据量如此大的 MySQL 集群进行日常维护(备份、集群节点水平扩容、实例迁移等)以及实例故障恢复都是一项比较耗时费力的工作。经过与研发讨论后决定将集群 C1 中比较大的两个库 DB1 和 DB2 拆分出来,组成一个新的 PXC 集群 C2。

集群拆分前后示意图如下(正常每个集群有三个节点,为简单起见,每个集群只画了一个节点):

e460af675f68779ef6f5e2e48ecce339.png

3. 方案简要说明

PXC 集群进行库的拆分,大致流程是使用当前集群 C1 的任意一个节点做一个全量副本,利用这个副本再做2个节点的数据,组建一个三节点的新集群 C2。同时为了保持数据的一致性,新集群 C2 的写节点作为原有集群 C1 某个节点的从库,不断同步集群 C1 的数据更新。

0977704410b3d6768464c42938e12392.png

原计划是第一步先迁移 DB1,主要流程为:

业务方下线集群 C1 上与 DB1 相关的应用服务,停止对该库中所有表的写入。

为了防止遗漏的应用服务对 DB1 进行写入,DBA 将该库里面所有的表进行改名,即加一个统一的后缀(需提前准备好脚本)。

DBA 确认两个集群直接主从同步无延迟后,在新集群 C2 上恢复 DB1 所有表的名称,即去掉第2步中添加的后缀(需提前准备好脚本)。

业务方发布新的应用服务(业务方已提前修改好代码中的数据源配置),开始访问集群 C2 中的 DB1,各系统验证业务是否正常。

第二步是在完成第一步之后,仍然保持两个集群之间主从同步关系,等使用 C2 中 DB1 相关的业务确认无问题后以同样的方式迁移 DB2。

全部迁移完后观察一段时间,确认各业务流程正常,最后删除两个集群中不需要的 DB。

其中第一步操作过程如下:

cb1a3deb7df0bef2827b9560bb08d6be.png

不过在顺利完成第一步后出现了意外,原本应该正常同步数据的两个集群出现了复制中断,根据报错信息发现大量的数据(除 DB1 之外的库)在集群 C2 上找不到对应的记录,由于两个集群中 DB2 的数据没法保证一致性,导致不得不中止后续的迁移计划,以至于集群 C2 上只完成了库 DB1 的迁移。

4. 问题分析与复现4.1 问题分析

正常来说,集群 C1 已经彻底停止(表名已改)了对 DB1 中表的写入,而集群 C2 上只会对 DB1 中表进行写入,其他库的写入不受影响,应该正常复制才对。

既然复制出现了问题,那么原有的“理所当然”的想法肯定存在不合理的地方。经过排查,我们发现了一个令人匪夷所思的问题,两个集群用作复制的两个节点,从库和主库的 GTID 的 部分竟然是一样的,导致从库在对 DB1 进行写入后,生成的 GTID 的 值比主库上大,当接收主库推送过来的 binlog 数据时,发现主库事务的 GTID 的 值比自己的小,于是从库直接选择了跳过该事务,并没有重放这部分 binlog,从而出现了主从数据不一样的情况。

4.2 复现过程

为什么新建的从库生成的 GTID 的 会和主库一样呢?为了找到问题的原因,我们在测试环境用同样的流程对出现的问题进行复现。

首先我们复盘了下搭建主从复制的过程,大致如下:

1、使用 Xtrabackup 备份集群 C1 某个节点的全量数据,并将数据传送到目的服务器,用于新建集群 C2 的第一个节点。

2、在目的服务器 apply 备份日志后,根据生成的文件 xtrabackup_ binlog_info 中的内容找到复制信息。

# catxtrabackup_binlog_info

mysql-bin.000015997 401 cdbc9-e228-ee17-496f-5c53bc36ae5b:1-1123,

c05582e9-dc11-ee14-6b06-c041b8b7ff2d:1-4,

da5e0de8-dc13-ee14-76e6-f074e061cc69:1-2

3、新建文件 grastate.dat,并根据 apply 后生成的文件 xtrabackup_galera_info中的内容填写 grastate.dat 文件信息。

# cat xtrabackup_galera_info

3faa7d16-23ee-11eb-94f9-3fbe474800d2:4

# vim grastate.dat# GALERA saved stateversion: 2.1uuid: 3faa7d16-23ee-11eb-94f9-3fbe474800d2seqno: 4safe_to_bootstrap: 1

4、 以 bootstrap-pxc 方式启动该实例,作为集群 C2 的第一个节点,并与老集群 C1 建立复制关系。

# 启动实例/etc/init.d/mysql.server -P 3311 bootstrap-pxcmysql> reset slave all;Query OK, 0 rows affected (0.00 sec)

# 建立新的复制mysql> set wsrep_on = 0;Query OK, 0 rows affected (0.00 sec)

mysql> reset master;Query OK, 0 rows affected (0.00 sec)

mysql> set wsrep_on = 1;Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL gtid_purged='401cdbc9-e228-ee17-496f-5c53bc36ae5b:1-1123,c05582e9-dc11-ee14-6b06-c041b8b7ff2d:1-4,da5e0de8-dc13-ee14-76e6-f074e061cc69:1-2';Query OK, 0 rows affected (0.01 sec)

mysql> change master to master_host='10.86.41.xxx',master_port=3306,master_user='replication',master_password='xxxxxxxxxx',master_auto_position=1;Query OK, 0 rows affected, 2 warnings (0.02 sec)

mysql> start slave;Query OK, 0 rows affected (0.00 sec)

# 集群C2此时的master信息mysql> show master statusG*************************** 1. row ***************************File: mysql-bin.000002Position: 271Binlog_Do_DB:Binlog_Ignore_DB:Executed_Gtid_Set: 401cdbc9-e228-ee17-496f-5c53bc36ae5b:1-1123,c05582e9-dc11-ee14-6b06-c041b8b7ff2d:1-4,da5e0de8-dc13-ee14-76e6-f074e061cc69:1-21 row in set (0.00 sec)

5、 向集群 C1 中未迁移的库 test2 中正常写入数据,观察主从 master 信息。

# 写入前集群C1的master状态mysql> show master statusG*************************** 1. row ***************************File: mysql-bin.000015Position: 997Binlog_Do_DB:Binlog_Ignore_DB:Executed_Gtid_Set: 401cdbc9-e228-ee17-496f-5c53bc36ae5b:1-1123,c05582e9-dc11-ee14-6b06-c041b8b7ff2d:1-4,da5e0de8-dc13-ee14-76e6-f074e061cc69:1-21 row in set (0.00 sec# 向集群C1的库test2中写入两个事务的数据后master状态mysql> use test2;mysql> insert into t values(13);Query OK, 1 row affected (0.00 sec)

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

mysql> show master statusG*************************** 1. row ***************************File: mysql-bin.000015Position: 1481Binlog_Do_DB:Binlog_Ignore_DB:Executed_Gtid_Set: 401cdbc9-e228-ee17-496f-5c53bc36ae5b:1-1123,c05582e9-dc11-ee14-6b06-c041b8b7ff2d:1-6, # 发生变化的GTIDda5e0de8-dc13-ee14-76e6-f074e061cc69:1-21 row in set (0.00 sec)

# 此时集群C2的master信息mysql> show master statusG*************************** 1. row ***************************File: mysql-bin.000002Position: 735Binlog_Do_DB:Binlog_Ignore_DB:Executed_Gtid_Set: 401cdbc9-e228-ee17-496f-5c53bc36ae5b:1-1123,c05582e9-dc11-ee14-6b06-c041b8b7ff2d:1-6, # 发生变化的GTID,同步正常da5e0de8-dc13-ee14-76e6-f074e061cc69:1-21 row in set (0.00 sec)

此时复制没有问题,数据也是正常的。

6、向集群 C2 中已迁移的库 test1 中写入两个事务的数据,观察主从 master 信 息。

mysql> insert into t values(7);Query OK, 1 row affected (0.00 sec)mysql> insert into t values(8);Query OK, 1 row affected (0.00 sec)

mysql> show master statusG*************************** 1. row ***************************File: mysql-bin.000002Position: 1209Binlog_Do_DB:Binlog_Ignore_DB:Executed_Gtid_Set: 401cdbc9-e228-ee17-496f-5c53bc36ae5b:1-1123,c05582e9-dc11-ee14-6b06-c041b8b7ff2d:1-8, # 写入后,从节点发生变化的GTIDda5e0de8-dc13-ee14-76e6-f074e061cc69:1-21 row in set (0.00 sec)

7、 此后如果集群 C1 上继续写入一个事务。

mysql> delete from t where id = 13; # 删除test2库t表中id=13的记录Query OK, 1 row affected (0.00 sec)# 集群C1的master信息mysql> show master statusG*************************** 1. row ***************************File: mysql-bin.000015Position: 1723Binlog_Do_DB:Binlog_Ignore_DB:Executed_Gtid_Set: 401cdbc9-e228-ee17-496f-5c53bc36ae5b:1-1123,c05582e9-dc11-ee14-6b06-c041b8b7ff2d:1-7, # GTID的gno增加1da5e0de8-dc13-ee14-76e6-f074e061cc69:1-21 row in set (0.00 sec)

# 集群C2的master信息mysql> show master statusG*************************** 1. row ***************************File: mysql-bin.000002Position: 1209Binlog_Do_DB:Binlog_Ignore_DB:Executed_Gtid_Set: 401cdbc9-e228-ee17-496f-5c53bc36ae5b:1-1123,c05582e9-dc11-ee14-6b06-c041b8b7ff2d:1-8, # GTID的gno没有发生变化,因为同步过来的事务的GTID的gno值比自己小,选择跳过da5e0de8-dc13-ee14-76e6-f074e061cc69:1-21 row in set (0.00 sec)

# 此时C1集群已经被删掉的记录,在C2集群仍然存在mysql> use test2;Database changedmysql> select * from t where id = 13;+----+| id |+----+| 13 |+----+1 row in set (0.00 sec)

从测试过程中发现,确实通过以上的方式搭建主从节点后,存在主从节点写入后 GTID 值的部分相同的情况,此时如果主从节点同时发生写入(针对不同的库),就会导致主从节点数据不一致。

4.3 问题原因

对问题复现过程进行分析后,发现整个过程有一步是多余的,即步骤3(新建 grastate.dat 文件),因为我们的目的是通过搭建从库的方式组建一个新的集群,而不是对原有集群扩增节点,所以在该 slave 节点(针对原集群而言)以 bootstrap 方式启动时,不需要指定原来的集群信息。

当以 bootstrap 方式启动 PXC 实例时,如果 grastate.dat 文件存在,那么该实例会从该文件中获取 uuid 参数的值,赋值给参数 wsrep_ cluster_state_uuid,同时该参数的值也决定了事务的 Galera GTID 中的 部分,所以导致这个实例的与原集群中节点的 相同,当作为主从的两个节点都有写入时,从库在应用 binlog 时就会出现冲突或者忽略的情况,导致主从数据不一致。

5. 如何改进

通过此次集群拆分过程中出现的问题,总结下原因以及改进措施,避免后续工作中出现类似情况:

5.1 原因

延用了前期类似经验的惯性思维。因为在此之前有过两次类似的迁移操作,只不过当时只需迁移一个库,在原集群停止该库的写入后,等从库复制无延迟后就马上断开了复制,所以没有出现后续复制的问题。

操作流程不够精细。操作过程中没有严格区分 PXC 集群新增节点和拆分集群的流程差异,细节之处欠缺考虑,也反映出个人在对 PXC 的使用和原理方面研究不够深入。5.2 改进措施

分别制定 PXC 集群新增节点和拆分集群的操作规范,在运维操作时严格按照规范执行。

优化集群拆分方案。比如可建立一个中间节点,对要迁移的数据库进行过滤复制,然后再同步到新集群中,可节省组建新集群的时间,同时可避免后续在新集群上删除多余的库。

81c7d9806c877839e4d2c51cd540fc24.png

3. 在标准规范的基础上,实现运维操作自动化,避免人为主观因素造成影响。

6. 关于 Galera GTID 与 MySQL GTID 的比较6.1 GTID 的概念

GTID 特性是 MySQL5.6加入的一个强大的特性,全称是 Global Transaction Identifier。MySQL 会为每一个 DML/DDL 操作增加一个唯一标记叫做 GTID,这个标记在整个复制环境中都是唯一的,格式为 。

GTID 相关的几个常见术语:

server_ uuid:单个 GTID 的前半部分,即 部分,是一个32字节+1字节(/0)的字符串。

gno:单个 GTID 的后半部分,即 部分,表示事务的序号,gno 的值从全局计数器 next_ free_ gno 中获取的。

GTID SET:表示一个 GTID 的集合,可以包含多个 server_ uuid,如 executed_ gtid、gtid_ purged。

GTID SET Interval:GTID SET 中某个 server_uuid 可能包含多个区间,比如 GTID 为“23d45aa2-3d1f-11e6-a16b-c81f66e1165d:1-99:110-200”的字符串中,GTID SET Interval 分别是“1-99”和“110-200”。6.2 GTID 的生成

GTID 是在 SQL 的 commit 命令发起后,order commit 执行到 flush 阶段需要生成 GTID Event 的时候才会获取。MySQL 内部维护了一个全局的 GTID 的计数器 next_ free_gno 用于生成 gno。

可参考函数 Gtid_ state∶getautomatic_gno,部分代码如下∶

// 定义∶Gtid next_candidate={ sidno,sidno == get_server_sidno? next_free_gno: 1};// 赋值∶while( true){constGtid_set::Interval *iv= ivit.getO;// 定义IntervaL指针指向这个链表指针开头,如果在进行下次循环会获得NULLrpl_gno next_interval_start=iv != NULL? iv->start: MAX_GNO;// 正常情况下不会为NULL,因此 next_interval_start 等于第一个interval的start,当然如果初始化会为NULL,如果Interval->next =NULL 则标示设有区间了。while(next_candidate.gno < next_interval_start &&DBUG_EVALUATE_IF( "simulate_gno_exhausted", false, true))// 如果next_candidate.gno正常不会小于next_intervalL_start// 如果Interval->next =NULL或者初始化next_interval_start会被置为MAX_GNO,那么条件成立DBUG_RETURN(next_candidate.gno);// 返回了这个gno 则GTID生成{// 返回gno,GTID生成if(owned_gtids.get_ownernext_candidate)==O)DBUG_RETURN(next_candidate.gno)// 如果本GTID已经被其他线程占用,则next_candidate.gno++ 继续判断next_candidate.gno++;}......}

6.3 server_uuid 的生成

MySQL 在启动的时候会调用 init_ server_auto_ options 来读取 auto.cnf 文件。如果 auto.cnf 文件不存在,则会调用函数 generate_server_ uuid 来生成一个新的 server_uuid,这时 GTID 会发生改变。

当 auto.cnf 文件不存在时,调用函数 generate_ serve_ruid 生成 server_ uuid 的过程中可以看出,server_uuid 的生成至少和下面部分有关∶

数据库的启动时间。

线程的 LWP ID。LWP 是轻量级进程(light-weight process)的简称。

一个随机的内存地址。

下面是部分代码供参考∶

// 获取MySqL启动时间consttime_t save_server_start_time=server_start_time;// 加入LWP号运算server_start_time+=((ulonglong)current_pid << 48)+current_pid;// 一个内存指针,即线程结构体的内存地址thd->status_var.bytes_sent=(ulonglong)thd;// 具体的运算过程lex_start(thd);func_uuid= new(thd->mem_root)Item_func_uuid;func_uuid->fixed= 1;func_uid->vaL_str(&uuid);

6.4 Galera GTID

PXC 集群记录事务的 Galera GTID 中 的生成逻辑与 MySQL GTID 的不太一样,而且也不是 PXC 集群的 wsrep_ cluster_state_uuid,还是以上面的 PXC 集群 C2 为例,看下这个几个参数的值:

mysql> select @@server_uuid;+--------------------------------------+| @@server_uuid |+--------------------------------------+| 4fd32e4d-249f-11eb-8fd9-fa163e05f092 |+--------------------------------------+1row inset ( 0. 00sec)mysql> select @@global.gtid_executed;+---------------------------------------------------------------------------------------------------------------------------------+| @@global.gtid_executed |+---------------------------------------------------------------------------------------------------------------------------------+| 401cdbc9-e228-ee17-496f-5c53bc36ae5b:1-1123,c05582e9-dc11-ee14-6b06-c041b8b7ff2d:1-8,da5e0de8-dc13-ee14-76e6-f074e061cc69:1-2 |+---------------------------------------------------------------------------------------------------------------------------------+1row inset ( 0. 00sec)

mysql> show status like 'wsrep_%_uuid';+--------------------------+--------------------------------------+| Variable_name |Value |+--------------------------+--------------------------------------+|wsrep_local_state_uuid | 3faa7d16-23ee-11eb-94f9-3fbe474800d2 || wsrep_gcomm_uuid |4f807d05- 249f- 11eb-a679-ea70d2c3575a ||wsrep_cluster_state_uuid | 3faa7d16-23ee-11eb-94f9-3fbe474800d2 |+--------------------------+--------------------------------------+3rows inset ( 0. 00sec)

可以看到,PXC 集群中实例的 server_ uuid 并不在它的 GTID SET 中,当 PXC 集群写入数据时,生成的 MySQL GTID 的,也不是服务器的 server_uuid。

实际上在 PXC 集群中这么设计合理的,因为 PXC 是一个分布式可多写的集群架构,所有节点共享相同的 ,当在不同的节点写入数据时,将产生同样的 GTID SET,看起来不同的事务像是在同一个服务器上执行的。

6.5 Galera GTID vs MySQL GTID

两种 GTID 使用的格式相同,即 。

对于 Galera 来说,在集群以 bootstrap 启动时会生成 ,且集群中的所有节点共享此 。

所以说 PXC 集群中各节点之间用作同步的 Galera GTID 和 MySQL GTID 之间并没有直接关系,在运维过程中切记不要搞混淆。

参考资料:

1、简书专栏《深入理解主从原理32讲》 作者:重庆八怪2、《MySQL 运维内参》 作者:周彦伟、王竹峰、强昌金

责任编辑:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459839.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java_IO总结(一)

所谓IO&#xff0c;也就是Input与Output的缩写。在java中&#xff0c;IO涉及的范围比较大&#xff0c;这里主要讨论针对文件内容的读写 其他知识点将放置后续章节&#xff08;我想&#xff0c;文章太长了&#xff0c;谁都没耐心翻到最后&#xff09; 对于文件内容的操作主要分为…

ocsng mysql connection problem_OCSNG 介绍及其工作原理

OCSNG部署&#xff1a;http://wowking.blog.51cto.com/1638252/994441OCSNG 是什么呢&#xff1f;OCSNG就是Open Computer and Software Inventory Next Generation是一款免费软件&#xff0c;它使用户能够盘点网络工程师的IT资产。OCS-NG收集有关运行OCS客户端程序(“OCS Inve…

hdu--5135--贪心

尽量选边数大的3根木棍来组成一个三角形 一直到无法选取为止 这边计算三角形面积 还是用 海伦公式比较方便 1 #include <iostream>2 #include <algorithm>3 #include <cmath>4 #include <cstring>5 #include <iomanip>6 using namespace std;7 …

【Daily Scrum】12-08

因为TFS的一些问题&#xff0c;到现在一直都看不了Sprint 3的burndown and burn rate. 今天的scrum发现这个Sprint期间大家组里的事情都比较多&#xff0c;不过大家还是有很努力地在晚上和周末来完成ASC Master的任务&#xff0c;辛苦~ Member Today’s WorkTomorrow’s WorkFe…

java 字符串转成图片_java 转换图片为字符串,将字符串转换成图片显示

java 转换图片为字符串&#xff0c;将字符串转换成图片显示&#xff0c;该方法只适用于比较小的图片传输&#xff0c;50K以内&#xff1a;try{// 将图片转换成字符串File imgFile new File("f:\\Vista.png");FileInputStream fis new FileInputStream( imgFile );b…

转移指令检测题9

补全编程&#xff0c;利用loop指令&#xff0c;实现在内存2000H段中查找第一个值为0的字节&#xff0c;找到后&#xff0c;将它的偏移地址存储在DX中 assume cs:code code segment start:mov ax,2000h mov ds,ax mov bx,0 s: mov cl,[bx] mov ch,0 inc cx ;此处为要…

c语言 java append_C++中append函数的用法和函数定义。谢谢!

展开全部要想使用标准C中string类&#xff0c;必须要包含#include // 注意是&#xff0c;不62616964757a686964616fe78988e69d8331333339663434是&#xff0c;带.h的是C语言中的头文件using std::string;using std::wstring;或using namespace std;下面你就可以使用string/wstr…

很好用的程序员在线画图软件

今天向大家推荐一个很好用的在线画图软件&#xff1a;今天向大家推荐一个很好用的在线画图软件&#xff1a;今天向大家推荐一个很好用的在线画图软件&#xff1a;&#xff08;重要的事情说三篇&#xff09;连接地址如下&#xff1a;https://www.processon.com/i/55e3195de4b0df…

java breakpoint_java断点

第一步&#xff1a;用firefox运行程序&#xff0c;当点击保存&#xff0c;提示保存失败后&#xff0c;启动firebug通过请求找到addNew.ezt出现错误&#xff0c;在eztnews.xml里通过ctrlF查找找到请求执行的类和方法找到NewsAction类的doAddNew方法然后在通过找到NewsActions.ja…

OC之ARC环境中的循环strong问题

2019独角兽企业重金招聘Python工程师标准>>> main.m文件&#xff1a; #import <Foundation/Foundation.h> #import "Person.h" #import "Dog.h"int main() {Person *p [[Person alloc] init];Dog *d [[Dog alloc] init];p.dog d;d.per…

Android自定义view之圆形进度条

本节介绍自定义view-圆形进度条思路&#xff1a;根据前面介绍的自定义view内容可拓展得之&#xff1b;1&#xff1a;新建类继承自View2&#xff1a;添加自定义view属性3&#xff1a;重写onDraw(Canvas canvas)4&#xff1a;实现功能下面上代码1.自定义view代码&#xff1a; pub…

java二级考试备考_2017计算机二级考试《JAVA》备考测试题「带答案」

2017计算机二级考试《JAVA》备考测试题「带答案」为确保同学们将所涉及的考点全面复习到位&#xff0c;让大家充满信心的步入考场&#xff0c;以下是百分网小编搜索整理的一份计算机二级考试《JAVA》备考测试题【带答案】&#xff0c;供参考练习&#xff0c;希望对大家有所帮助…

java流类图结构_java学习之IO流(学习之旅,一)

个人在学习IO流的时候看到如下所示java 流类图结构的时候&#xff0c;我的感想是&#xff0c;这么多处于蒙的状态。Java流类图结构这么多&#xff0c;没有分类不好学&#xff0c;那我们就慢慢一口一口的吃&#xff0c;这样每天学习一点就好了&#xff0c;其实很多类并不是常用的…

php 安装xdebug扩展

php 扩展获取地址 http://pecl.php.net/package/ 编译安装的过程 wget http://pecl.php.net/get/xdebug-2.2.2.tgz tar -zxvf xdebug-2.2.2.tgz cd xdebug-2.2.2/ /data/klj/php/bin/phpize ./configure --enable-xdebug --with-php-config/data/klj/php/bin/php-config mak…

拨打电话 java_简单拨打电话程序

众所周知,对于一个手机,能拨打电话是其最重要也是最常用的一个功能.而在Android里是怎么样实现拨打电话的程序呢?我在这里写了一个简单的拨打电话的Demo,供大家参考.一共分为5个步骤.Step 1:新建一个Android工程,命名为phoneCallDemo.Step 2:设计程序的界面,打开main.xml把内容…

WPF01(xaml)

XAML&#xff1a;&#xff08;转自http://www.cnblogs.com/huangxincheng/archive/2012/06/17/2552511.html&#xff09; <Window x:Class"WpfApplication1.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"…

java 线程 状态 图_Java提高——多线程(一)状态图

操作系统中的进程和线程的概念进程是指一个内存运行的应用程序&#xff0c;每个进程都有自己独立的一块内存空间&#xff0c;一个进程中可以启动多个线程&#xff0c;比如windows下的一个运行的应用程序.exe就是一个进程。线程是指进程中的一个执行流&#xff0c;一个进程可以运…

幽幽的灵光射不出你想要的疯狂

秋天到了&#xff0c;忧伤便无处可逃&#xff0c;秋天的忧伤的气息&#xff0c;就像一个妖艳的美女躺在你的身边&#xff0c;让你热血沸腾&#xff0c;冲动无比&#xff0c;而又悲喜交加&#xff0c;忧愁满地。如果不信&#xff0c;你可以试试。分享一首去年的诗歌&#xff0c;…

找规律

找规律填写NN方阵。如N8时, 其方阵为: 1 1 1 1 1 1 1 11 2 2 2 2 2 2 11 2 3 3 3 3 2 11 2 3 4 4 3 2 11 2 3 4 4 3 2 11 2 3 3 3 3 2 11 2 2 2 2 2 2 11 1 1 1 1 1 1 1 上代码&#xff1a; 1 #include <stdio.h&g…

arm qt5 iconv 问题

2019独角兽企业重金招聘Python工程师标准>>> 问题 3&#xff1a;./system/rootlib/helloworld -qws &#xff0c;程序运行起来&#xff0c;仍报错 QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed …