您好,欢迎来到要发发知识网。
搜索
您的当前位置:首页正文

MySQL高性能优化实战总结

2023-11-12 来源:要发发知识网

这个参数决定了Linux是倾向于使用swap,还是倾向于释放文件系统cache。在内存紧张的情况下,数值越低越倾向于释放文件系统cache。当然,这个参数只能减少使用swap的概率,并不能避免Linux使用swap。

修改MySQL的配置参数innodb_flush_method,开启O_DIRECT模式。这种情况下,InnoDB的buffer pool会直接绕过文件系统cache来访问磁盘,但是redo log依旧会使用文件系统cache。值得注意的是,Redo log是覆写模式的,即使使用了文件系统的cache,也不会占用太多

IO调度策略

  1. #echo deadline>/sys/block/sda/queue/scheduler #临时修改为deadline  
  2. 永久修改如下:  
  3. vi /boot/grub/grub.conf  
  4. 更改到如下内容:  
  5. kernel /boot/vmlinuz-2.6.18-8.el5 ro root=LABEL=/ elevator=deadline rhgb quiet 

1.5.5 系统参数调整

Linux系统内核参数优化

  1. vim /etc/sysctl.conf   
  2.  net.ipv4.ip_local_port_range = 1024 65535 # 用户端口范围   
  3.  net.ipv4.tcp_max_syn_backlog = 4096   
  4.  net.ipv4.tcp_fin_timeout = 30   
  5.  fs.file-max=65535 # 系统最大文件句柄,控制的是能打开文件最大数量 

用户限制参数(mysql可以不设置以下配置)

  1. vim /etc/security/limits.conf   
  2.  * soft nproc 65535   
  3.  * hard nproc 65535   
  4.  * soft nofile 65535   
  5.  * hard nofile 65535 

1.5.6 应用优化

业务应用和数据库应用独立,防火墙:iptables、selinux等其他无用服务(关闭):

  1. chkconfig --level 23456 acpid off   
  2. chkconfig --level 23456 anacron off   
  3. chkconfig --level 23456 autofs off   
  4. chkconfig --level 23456 avahi-daemon off  
  5. chkconfig --level 23456 bluetooth off   
  6. chkconfig --level 23456 cups off   
  7. chkconfig --level 23456 firstboot off   
  8. chkconfig --level 23456 haldaemon off   
  9. chkconfig --level 23456 hplip off   
  10. chkconfig --level 23456 ip6tables off   
  11. chkconfig --level 23456 iptables off   
  12. chkconfig --level 23456 isdn off   
  13. chkconfig --level 23456 pcscd off   
  14. chkconfig --level 23456 sendmail off   
  15. chkconfig --level 23456 yum-updatesd off 

安装图形界面的服务器不要启动图形界面 runlevel 3,另外,思考将来我们的业务是否真的需要MySQL,还是使用其他种类的数据库。用数据库的最高境界就是不用数据库。

1.6 数据库优化

SQL优化方向:

执行计划、索引、SQL改写

架构优化方向:

高可用架构、高性能架构、分库分表

1.6.1 数据库参数优化

调整:

实例整体(高级优化,扩展)

  1. thread_concurrency #并发线程数量个数   
  2. sort_buffer_size #排序缓存   
  3. read_buffer_size #顺序读取缓存   
  4. read_rnd_buffer_size #随机读取缓存   
  5. key_buffer_size #索引缓存   
  6. thread_cache_size #线程缓存(1G—>8, 2G—>16, 3G—>32, >3G—>64) 

连接层(基础优化)

设置合理的连接客户和连接方式

  1. max_connections #最大连接数,看交易笔数设置   
  2. max_connect_errors #最大错误连接数,能大则大   
  3. connect_timeout #连接超时   
  4. max_user_connections #最大用户连接数  
  5. skip-name-resolve #跳过域名解析   
  6. wait_timeout #等待超时   
  7. back_log #可以在堆栈中的连接数量 

SQL层(基础优化)

  •  query_cache_size: 查询缓存
  •  OLAP类型数据库,需要重点加大此内存缓存.
  •  但是一般不会超过GB.
  •  对于经常被修改的数据,缓存会立马失效。
  •  我们可以实用内存数据库(redis、memecache),替代他的功能。
  • 1.6.2 存储引擎层(innodb基础优化参数)

    1. default-storage-engine   
    2. innodb_buffer_pool_size # 没有固定大小,50%测试值,看看情况再微调。但是尽量设置不要超过物理内存70% innodb_file_per_table=(1,0)   
    3. innodb_flush_log_at_trx_commit=(0,1,2) #1是最安全的,0是性能最高,2折中   
    4. binlog_sync   
    5. Innodb_flush_method=(O_DIRECT, fdatasync)   
    6. innodb_log_buffer_size #100M以下   
    7. innodb_log_file_size #100M 以下   
    8. innodb_log_files_in_group #5个成员以下,一般2-3个够用(iblogfile0-N)   
    9. innodb_max_dirty_pages_pct #达到百分之75的时候刷写 内存脏页到磁盘。 log_bin   
    10. max_binlog_cache_size #可以不设置   
    11. max_binlog_size #可以不设置   
    12. innodb_additional_mem_pool_size #小于2G内存的机器,推荐值是20M。32G内存以上100M 

     

    MySQL高性能优化实战总结

    标签:tab   参数   tst   需求   注意   境界   iptable   内存缓存   name   

    小编还为您整理了以下内容,可能对您也有帮助:

    mysql中casewhen太多有没有好的优化方案,使sql好维护?

    优化口诀

    全值匹配我最爱,最左前缀要遵守,

    带头大哥不能死,中间兄弟不能断。

    索引列上少计算,范围之后全失效,

    LIKE百分写最右,覆盖索引不写星,

    不等空值还有or,索引失效要少用。

    具体含义见下文实战。

    准备

    1.创建test表

    drop table if exists test;create table test(id int primary key auto_increment,c1 varchar(10),c2 varchar(10),c3 varchar(10),c4 varchar(10),c5 varchar(10)) ENGINE=INNODB default CHARSET=utf8;insert into test(c1,c2,c3,c4,c5) values('a1','a2','a3','a4','a5');insert into test(c1,c2,c3,c4,c5) values('b1','b2','b3','b4','b5');insert into test(c1,c2,c3,c4,c5) values('c1','c2','c3','c4','c5');insert into test(c1,c2,c3,c4,c5) values('d1','d2','d3','d4','d5');insert into test(c1,c2,c3,c4,c5) values('e1','e2','e3','e4','e5');

    2.创建索引

    此时索引数据结构如下:

    分析Case索引使用情况

    Case 1:

    分析:

    创建复合索引的顺序为c1,c2,c3,c4。

    上述四组explain执行的结果都一样:type=ref,key_len=132,ref=const,const,const,const。

    结论:在执行常量等值查询时,改变索引列的顺序并不会更改explain的执行结果,因为mysql底层优化器会进行优化,但是推荐按照索引顺序列编写sql语句。

    Case 2:

    分析:当出现范围的时候,type=range,key_len=99,比不用范围key_len=66增加了,说明使用上了索引,但对比Case1中执行结果,说明c4上索引失效。

    结论:范围右边索引列失效,但是范围当前位置(c3)的索引是有效的,从key_len=99可证明。

    数据结构分析:当索引走了 >c3后,此时在索引树形结构中c4已经无序了,没有办法走索引。

    Case 2.1:

    分析:与上面explain执行结果对比,key_len=132说明索引用到了4个,因为对此sql语句mysql底层优化器会进行优化:范围右边索引列失效(c4右边已经没有索引列了),注意索引的顺序(c1,c2,c3,c4),所以c4右边不会出现失效的索引列,因此4个索引全部用上。

    结论:范围右边索引列失效,是有顺序的:c1,c2,c3,c4,如果c3有范围,则c4失效,因为c3范围查询之后,c4索引数将不是有序,c4当然失效;如果c4有范围,则没有失效的索引列,从而会使用全部索引,c4范围查询后,不影响索引数的顺序。

    Case 2.2:

    分析:如果在c1处使用范围,则type=ALL,key=Null,索引失效,全表扫描,这里违背了最佳左前缀法则,带头大哥已死,因为c1主要用于范围,而不是查询。

    解决方式是使用覆盖索引。

    结论:在最佳左前缀法则中,如果最左前列(带头大哥)的索引失效,则后面的索引都失效。

    Case 3:

    分析:

    利用最佳左前缀法则:中间兄弟不能断,因此用到了c1和c2索引(查找),从key_len=66,ref=const,const,c3索引列用在排序过程中。

    Case 3.1:

    分析:从explain的执行结果来看:key_len=66,ref=const,const,从而查找只用到c1和c2索引,c3索引用于排序。

    Case 3.2:

    分析:从explain的执行结果来看:key_len=66,ref=const,const,查询使用了c1和c2索引,由于用了c4进行排序,跳过了c3,出现了Using filesort。

    Case 4:

    分析:查找只用到索引c1,c2和c3用于排序,无Using filesort。

    Case 4.1:

    分析:和Case 4中explain的执行结果一样,但是出现了Using filesort,因为索引的创建顺序为c1,c2,c3,c4,但是排序的时候c2和c3颠倒位置了。

    Case 4.2:

    分析:在查询时增加了c5,但是explain的执行结果一样,因为c5并未创建索引。

    Case 4.3:

    分析:与Case 4.1对比,在Extra中并未出现Using filesort,因为c2为常量,在排序中被优化,所以索引未颠倒,不会出现Using filesort。

    Case 5:

    分析:只用到c1上的索引,因为c4中间间断了,根据最佳左前缀法则,所以key_len=33,ref=const,表示只用到一个索引。

    Case 5.1:

    分析:对比Case 5,在group by时交换了c2和c3的位置,结果出现Using temporary和Using filesort,极度恶劣。原因:c3和c2与索引创建顺序相反。

    Case 6:

    分析:

    在c1,c2,c3,c4上创建了索引,直接在c1上使用范围,导致了索引失效,全表扫描:type=ALL,ref=Null。因为此时c1主要用于排序,并不是查询。

    使用c1进行排序,出现了Using filesort。

    解决方法:使用覆盖索引。

    Case 7:

    分析:虽然排序的字段列与索引顺序一样,且order by默认升序,这里c2 desc变成了降序,导致与索引的排序方式不同,从而产生Using filesort。

    Case 8:

    分析:对于排序来说,多个相等条件也是范围查询。

    总结

    MySQL支持两种方式的排序filesort和index,Using index是指MySQL扫描索引本身完成排序。index效率高,filesort效率低。

    order by满足两种情况会使用Using index。

    order by语句使用索引最左前列。

    使用where子句与order by子句条件列组合满足索引最左前列。

    尽量在索引列上完成排序,遵循索引建立(索引创建的顺序)时的最佳左前缀法则。

    如果order by的条件不在索引列上,就会产生Using filesort。

    group by与order by很类似,其实质是先排序后分组,遵照索引创建顺序的最佳左前缀法则。注意where高于having,能写在where中的限定条件就不要去having限定了。

    ————————————————

    版权声明:本文为CSDN博主「weixin_39733232」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/weixin_39733232/article/details/111390836

    MySQL表连接之驱动表与被驱动表

    众所周知, MySQL的驱动表与被驱动表是优化器自动优化选择的结果 (与表连接的前后顺序等无关),我们可以用explain执行计划来知晓:

    如上所示,前面一行t1是驱动表,后面一行t2是被驱动表。那么驱动表与被驱动表的选择是否有规律可循呢?下面是百度搜索两个主流的博文对驱动表与被驱动表的阐释:

    1. MySQL连接查询驱动表被驱动表以及性能优化 - 阿伟~ - 博客园 博文A 主要结论:

    2. mysql驱动表与被驱动表及join优化_java小小小黑的博客-CSDN博客_mysql驱动表和被驱动表 博文B 其主要结论:

    两个帖子的结论是都差不多,而且还给出了例子来佐证。那么网上的结论是否权威?是否有普遍性?是否存在缺陷?

    让我们来一起打破砂锅问到底。下面有两张表结构一模一样的表t1,t2:其中t1 100条数据,t2 1000条数据;t1(t2)结构如下:

    按照上面博文的结论,left join左边是t2表,应该是驱动表。我们查看下结果:

    与 博文B 中观点1相违背(同理观点2也违背),与实际不符,但究竟这是为什么呢?

    下面发一张MySQL的执行过程(来源于《MySQL实战45讲》中01讲【一条SQL查询语句是如何执行的】)

    so die si ne,原来sql执行的过程是这样呀。等等,不对,这跟刚才SQL又有什么关系,上面left join中t2表还是左边的呀。

    我们知道MySQL高版本的性能越来越好,它是不断进行优化迭代的。远古的mysql版本可能还需要人工把小表放在前面,大表放在后面等这些需要人工调优的经验早就已经被解决了。也就是说我们写的语句,MySQL为了追求更好的效率,它在执行器执行前已经帮我们优化了。那么实际优化后的sql如何查看呢?用show warning命令:

    其中Message就是优化后实际执行的sql语句,格式化后如下:

    优化后left join左连接变成了内连接(inner) join。所以用优化后的sql看,表t1是小表所以作为驱动表,与实际结果相符。

    left join 竟然优化成了join,太神奇了,但这是为什么呢?原因在于mysql中null与任何值做等值或者不等值比较的时候都是null,即使是select null=null 也是null。这样where 条件t1.a=t2.a查询条件不会包含t2.a为NULL的行,实际效果其实跟join一样,被优化器智能的优化了。

    我们直接看执行计划看实际结果吧:

    结果显示t2是驱动表,t1是被驱动表。t2是1000条数据按理说是大表应该是被驱动表,与 博文A , 博文B 的结论又不一致了。

    《MySQL实战45讲》中34讲【到底可不可以使用join】已经讲的很透彻了,很深入了,我就不在这里献丑了。啰嗦几句大概就是驱动表是全表扫描不走索引,所以选被驱动表t1可以走索引,不会全表扫描,减少IO次数,性能高。里面对大表小表的总结,简直是精髓,特意在此再次着重强调:

    在决定哪个表做驱动表的时候,应该是两个表按照各自的条件过滤,过滤完成之后,计算参与join的各个字段的总数据量,数据量小的那个表,就是“小表”,应该作为驱动表。

    按照上面分析,我们先思考下MySQL会选择哪张表作为驱动表呢?

    表t1,t2在字段a上都有索引不会全表扫描,其中t1.a=5条件过滤后只有一条,很显然嘛,t1数据量少是小表,肯定是驱动表,错不了,再说了前面的红色粗体已经强调了,不会有错的。

    有冇搞错?事实又被打脸了。还记得在开篇我们说过的mysql优化器会对sql语句进行优化的吗?下面我们看下执行计划与优化的sql语句:

    格式化后的优化SQL如下:

    优化后两表t1,t2都走索引,并且都只有一条结果返回,因此都只会扫描一行,数据量一样,所以谁在前面谁就是驱动表,也就是上面sql中表t2。一切都释然,豁然开通!

    回头再仔细想想,高,实在是高!仔细深思之后MySQL优化后的句子真让人猛拍大腿。高明之处在于:

    1. 本来join连接是个M*N的嵌套循环,优化后变成了M+N的判断,两表不再嵌套判断了。

    2. 优化后,两表没有多大必然联系,只需把两表的结果集拼接即可,互不干扰。如果mysql未来可以多线程查询,岂不十分快哉!

    小伙伴们还记得我们在上一章 MySQL索引初探 中编码类型不一致发生隐式转换时有时候走索引,有时候索引又失效的问题吗?下面我们选取有代表性的一条记录来分析:

    其中表demo_test总共有640条数据,demo_test_ass有3条数据。显然经过过滤条件t.rid>1完成后demo_test_ass数据量小,应该作为驱动表。虽然test.c_utf8mb4 = t.c2两字段连接中发生了t.c2字段发生隐式转换,但是实际上并不影响被驱动表test上的c_utf8mb4索引。

    好了,本章到此结束,让我们一起 总结一下MySQL驱动表与被驱动表的选取原则 :

    หน ง 同等条件,优先选取有索引的表作为被驱动表。 在此介绍一下什么叫同等条件,比如上面的②中的语句。 两表没有其他额外的过滤条件,因此选关联字段有索引的t1作为被驱动表。但是如果加了条件(and t1.id=3),此时t1数据量少,就选取了t2作为被驱动表。

    สอง MySQL选择驱动表与被驱动表是基于优化器优化后的,小表是驱动表,大表是被驱动表。 基于优化器优化后开篇的 博文A与B 结论成立。

    当然这都是我一家之言,并不是官方结论,目前暂未找到官方确切对于驱动表与被驱动表的解释,请大家踊跃拍砖!

    数据库消耗内存大还是cpu大

    作者 王文安,腾讯CSIG数据库专项的数据库工程师,主要负责腾讯云数据库 MySQL 的相关的工作,热爱技术,欢迎留言进行交流。文章首发于腾讯云+社区的腾讯云数据库专家服务专栏。

    在日常工作中,发现 MySQL 的状态不太对劲的时候,一般都会看看监控指标,很多时候会看到熟悉的一幕:CPU 使用率又爆了。本文将给大家介绍 MySQL 和 CPU 之间的关系,对此有一定的了解之后可以更准确的判断出问题的原因,也能够提前发现一些引发 CPU 问题的隐患。

    怎么看懂CPU使用率

    以 Linux 的 top 命令为例,效果如下:

    Top 命令

    在 %CPU 这一列就展示了 CPU 的使用情况,百分比指代的是总体上占用的时间百分比:

    %us:表示用户进程的 CPU 使用时间(没有通过 nice 调度)

    %sy:表示系统进程的 CPU 使用时间,主要是内核使用。

    %ni:表示用户进程中,通过 CPU 调度(nice)过的使用时间。

    %id:空闲的 CPU 时间

    %wa:CPU 运行时在等待 IO 的时间

    %hi:CPU 处理硬中断花费的时间

    %si:CPU 处理软中断花费的时间

    %st:被虚拟机偷走的 CPU 时间

    通常情况下,我们讨论的 CPU 使用率过高,指的是 %us 这个指标,监控里面的 CPU 使用率通常也是这个值(也有用其他的方法计算出来的,不过简单起见,不考虑其他的情况 )。其他几个指标过高也代表出 MySQL 的状态异常,简单起见,这里主要还是指 %us 过高的场景。

    MySQL和线程

    MySQL 是单进程多线程的结构,意味着独占的 MySQL 服务器里面,只能用 top 命令看到一行数据。

    TOP 命令效果

    这里能看到的是 MySQL 的进程 ID,如果要看到线程的情况,需要用top -H

    TOP 命令效果

    在这里能看到的是 MySQL 各个线程的 ID,可以看到 MySQL 在启动之后,会创建非常多的内部线程来工作。

    这些内部线程包括 MySQL 自己用来刷脏,读写数据等操作的系统线程,也包括处理用户 SQL 的线程,姑且叫做用户线程吧。用户线程有一个特殊的地方:程序端发送到 MySQL 端的 SQL,只会由一个用户线程来执行(one-thread-per-connection),所以 MySQL 在处理复杂查询的时候,会出现“一核有难,多核围观”的尴尬现象。

    参考 %us 的定义,对于 Linux 系统来说,MySQL 进程和它启动的所有线程都不算内核进程,因此 MySQL 的系统线程和用户线程在繁忙的时候,都会体现在 CPU 使用率的 %us 指标上。

    什么时候CPU会100%

    MySQL 干什么的时候,CPU 会 100%?从前文的分析来看,MySQL 主要是两类线程占用 CPU:系统线程和用户线程。因此 MySQL 独占的服务器上,只需要留意一下这两类线程的情况,就能 Cover 住绝大部分的问题场景。

    系统线程

    在实际的环境中,系统线程遇到问题的情况会比较少,一般来说,多个系统线程很少会同时跑满,只要服务器的可用核心数大于等于 4 的话,一般也不会遇到 CPU 100%,当然有一些 bug 可能会有影响,比如这个:

    MySQL BUG

    虽然情况比较少,但是在面对问题的常规排查过程中,系统线程的问题也是需要关注的。

    用户线程

    提到用户线程繁忙,很多时候肯定会第一时间凭经验想到慢查询。确实 90% 以上的时候都是“慢查询”引起的,不过作为方*,还是要根据分析再去得出结论的~

    参考 us% 的定义,是指用户线程占用 CPU 的时间多少,这代表着用户线程占用了大量的时间。

    一方面是在进行长时间的计算,例如:order by,group by,临时表,join 等。这一类问题可能是查询效率不高,导致单个 SQL 语句长时间占用 CPU 时间,也有可能是单纯的数据量比较多,导致计算量巨大。另一方面是单纯的 QPS 压力高,所以 CPU 的时间被用满了,比如 4 核的服务器用来支撑 20k 到 30k 的点查询,每个 SQL 占用的 CPU 时间并不多,但是因为整体的 QPS 很高,所以 CPU 的时间被占满了。

    问题的定位

    分析完之后,就要开始实战了,这里根据前文的分析给出一些经典的 CPU 100% 场景,并给出简要的定位方法作为参考。

    PS:系统线程的 bug 的场景 skip,以后有机会再作为详细的案例来分析。

    慢查询

    在 CPU 100% 这个问题已经发生之后,真实的慢查询和因为 CPU 100% 导致被影响的普通查询会混在一起,难以直观的看 processlist 或者 slowlog 来发现尊敬的大船,这时候就需要一些比较明确的特征来进行甄别。

    从前文的简单分析可以看出来,查询效率不高的慢查询通常有以下几种情况:

    全表扫描:Handler_read_rnd_next 这个值会大幅度突增,且这一类查询在 slowlog 中 row_examined 的值也会非常高。

    索引效率不高,索引选错了:Handler_read_next 这个值会大幅度的突增,不过要注意这种情况也有可能是业务量突增引起的,需要结合 QPS/TPS 一起看。这一类查询在 slowlog 中找起来会比较麻烦,row_examined 的值一般在故障前后会有比较明显的不同,或者是不合理的偏高。

    比如数据倾斜的场景,一个小范围的 range 查询在某个特定的范围内 row_examined 非常高,而其他的范围时 row_examined 比较低,那么就可能是这个索引效率不高。

    排序比较多:order by,group by 这一类查询通常不太好从 Handler 的指标直接判断,如果没有索引或者索引不好,导致排序操作没有消除的话,那么在 processlist 和 slowlog 通常能看到这一类查询语句出现的比较多。

    当然,不想详细的分析 MySQL 指标或者是情况比较紧急的话,可以直接在 slowlog 里面用 rows_sent 和 row_examined 做个简单的除法,比如 row_examined/rows_sent > 1000 的都可以拿出来作为“嫌疑人”处理。这类问题一般在索引方面做好优化就能解决。

    PS:1000 只是个经验值,具体要根据实际业务情况来定。

    计算量大

    这一类问题通常是因为数据量比较大,即使索引没什么问题,执行计划也 OK,也会导致 CPU 100%,而且结合 MySQL one-thread-per-connection 的特性,并不需要太多的并发就能把 CPU 使用率跑满。这一类查询其实是是比较好查的,因为执行时间一般会比较久,在 processlist 里面就会非常显眼,反而是 slowlog 里面可能找不到,因为没有执行完的语句是不会记录的。

    这一类问题一般来说有三种比较常规的解决方案:

    读写分离,把这一类查询放到平时业务不怎么用的只读从库去。

    在程序段拆分 SQL,把单个大查询拆分成多个小查询。

    使用 HBASE,Spark 等 OLAP 的方案来支持。

    高 QPS

    这一类问题单纯的就是硬件资源的瓶颈,不论是 row_examined/rows_sent 的比值,还是 SQL 的索引、执行计划,或者是 SQL 的计算量都不会有什么明显问题,只是 QPS 指标会比较高,而且 processlist 里面可能什么内容都看不到,例如:

    processlist

    总结

    实际上 CPU 100% 的问题其实不仅仅是单纯的 %us,还会有 %io,%sys 等,这些会涉及到 MySQL 与 Linux 相关联的一部分内容,展开来就会比较多了。本文仅从 %us 出发尝试梳理一下排查&定位的思路和方法,在分析 %io,%sys 等方面的问题时,也可以用类似的思路,从这些指标的意义开始,结合 MySQL 的一些特性或者特点,逐步理清楚表象背后的原因。

    数据库消耗内存大还是cpu大

    作者 王文安,腾讯CSIG数据库专项的数据库工程师,主要负责腾讯云数据库 MySQL 的相关的工作,热爱技术,欢迎留言进行交流。文章首发于腾讯云+社区的腾讯云数据库专家服务专栏。

    在日常工作中,发现 MySQL 的状态不太对劲的时候,一般都会看看监控指标,很多时候会看到熟悉的一幕:CPU 使用率又爆了。本文将给大家介绍 MySQL 和 CPU 之间的关系,对此有一定的了解之后可以更准确的判断出问题的原因,也能够提前发现一些引发 CPU 问题的隐患。

    怎么看懂CPU使用率

    以 Linux 的 top 命令为例,效果如下:

    Top 命令

    在 %CPU 这一列就展示了 CPU 的使用情况,百分比指代的是总体上占用的时间百分比:

    %us:表示用户进程的 CPU 使用时间(没有通过 nice 调度)

    %sy:表示系统进程的 CPU 使用时间,主要是内核使用。

    %ni:表示用户进程中,通过 CPU 调度(nice)过的使用时间。

    %id:空闲的 CPU 时间

    %wa:CPU 运行时在等待 IO 的时间

    %hi:CPU 处理硬中断花费的时间

    %si:CPU 处理软中断花费的时间

    %st:被虚拟机偷走的 CPU 时间

    通常情况下,我们讨论的 CPU 使用率过高,指的是 %us 这个指标,监控里面的 CPU 使用率通常也是这个值(也有用其他的方法计算出来的,不过简单起见,不考虑其他的情况 )。其他几个指标过高也代表出 MySQL 的状态异常,简单起见,这里主要还是指 %us 过高的场景。

    MySQL和线程

    MySQL 是单进程多线程的结构,意味着独占的 MySQL 服务器里面,只能用 top 命令看到一行数据。

    TOP 命令效果

    这里能看到的是 MySQL 的进程 ID,如果要看到线程的情况,需要用top -H

    TOP 命令效果

    在这里能看到的是 MySQL 各个线程的 ID,可以看到 MySQL 在启动之后,会创建非常多的内部线程来工作。

    这些内部线程包括 MySQL 自己用来刷脏,读写数据等操作的系统线程,也包括处理用户 SQL 的线程,姑且叫做用户线程吧。用户线程有一个特殊的地方:程序端发送到 MySQL 端的 SQL,只会由一个用户线程来执行(one-thread-per-connection),所以 MySQL 在处理复杂查询的时候,会出现“一核有难,多核围观”的尴尬现象。

    参考 %us 的定义,对于 Linux 系统来说,MySQL 进程和它启动的所有线程都不算内核进程,因此 MySQL 的系统线程和用户线程在繁忙的时候,都会体现在 CPU 使用率的 %us 指标上。

    什么时候CPU会100%

    MySQL 干什么的时候,CPU 会 100%?从前文的分析来看,MySQL 主要是两类线程占用 CPU:系统线程和用户线程。因此 MySQL 独占的服务器上,只需要留意一下这两类线程的情况,就能 Cover 住绝大部分的问题场景。

    系统线程

    在实际的环境中,系统线程遇到问题的情况会比较少,一般来说,多个系统线程很少会同时跑满,只要服务器的可用核心数大于等于 4 的话,一般也不会遇到 CPU 100%,当然有一些 bug 可能会有影响,比如这个:

    MySQL BUG

    虽然情况比较少,但是在面对问题的常规排查过程中,系统线程的问题也是需要关注的。

    用户线程

    提到用户线程繁忙,很多时候肯定会第一时间凭经验想到慢查询。确实 90% 以上的时候都是“慢查询”引起的,不过作为方*,还是要根据分析再去得出结论的~

    参考 us% 的定义,是指用户线程占用 CPU 的时间多少,这代表着用户线程占用了大量的时间。

    一方面是在进行长时间的计算,例如:order by,group by,临时表,join 等。这一类问题可能是查询效率不高,导致单个 SQL 语句长时间占用 CPU 时间,也有可能是单纯的数据量比较多,导致计算量巨大。另一方面是单纯的 QPS 压力高,所以 CPU 的时间被用满了,比如 4 核的服务器用来支撑 20k 到 30k 的点查询,每个 SQL 占用的 CPU 时间并不多,但是因为整体的 QPS 很高,所以 CPU 的时间被占满了。

    问题的定位

    分析完之后,就要开始实战了,这里根据前文的分析给出一些经典的 CPU 100% 场景,并给出简要的定位方法作为参考。

    PS:系统线程的 bug 的场景 skip,以后有机会再作为详细的案例来分析。

    慢查询

    在 CPU 100% 这个问题已经发生之后,真实的慢查询和因为 CPU 100% 导致被影响的普通查询会混在一起,难以直观的看 processlist 或者 slowlog 来发现尊敬的大船,这时候就需要一些比较明确的特征来进行甄别。

    从前文的简单分析可以看出来,查询效率不高的慢查询通常有以下几种情况:

    全表扫描:Handler_read_rnd_next 这个值会大幅度突增,且这一类查询在 slowlog 中 row_examined 的值也会非常高。

    索引效率不高,索引选错了:Handler_read_next 这个值会大幅度的突增,不过要注意这种情况也有可能是业务量突增引起的,需要结合 QPS/TPS 一起看。这一类查询在 slowlog 中找起来会比较麻烦,row_examined 的值一般在故障前后会有比较明显的不同,或者是不合理的偏高。

    比如数据倾斜的场景,一个小范围的 range 查询在某个特定的范围内 row_examined 非常高,而其他的范围时 row_examined 比较低,那么就可能是这个索引效率不高。

    排序比较多:order by,group by 这一类查询通常不太好从 Handler 的指标直接判断,如果没有索引或者索引不好,导致排序操作没有消除的话,那么在 processlist 和 slowlog 通常能看到这一类查询语句出现的比较多。

    当然,不想详细的分析 MySQL 指标或者是情况比较紧急的话,可以直接在 slowlog 里面用 rows_sent 和 row_examined 做个简单的除法,比如 row_examined/rows_sent > 1000 的都可以拿出来作为“嫌疑人”处理。这类问题一般在索引方面做好优化就能解决。

    PS:1000 只是个经验值,具体要根据实际业务情况来定。

    计算量大

    这一类问题通常是因为数据量比较大,即使索引没什么问题,执行计划也 OK,也会导致 CPU 100%,而且结合 MySQL one-thread-per-connection 的特性,并不需要太多的并发就能把 CPU 使用率跑满。这一类查询其实是是比较好查的,因为执行时间一般会比较久,在 processlist 里面就会非常显眼,反而是 slowlog 里面可能找不到,因为没有执行完的语句是不会记录的。

    这一类问题一般来说有三种比较常规的解决方案:

    读写分离,把这一类查询放到平时业务不怎么用的只读从库去。

    在程序段拆分 SQL,把单个大查询拆分成多个小查询。

    使用 HBASE,Spark 等 OLAP 的方案来支持。

    高 QPS

    这一类问题单纯的就是硬件资源的瓶颈,不论是 row_examined/rows_sent 的比值,还是 SQL 的索引、执行计划,或者是 SQL 的计算量都不会有什么明显问题,只是 QPS 指标会比较高,而且 processlist 里面可能什么内容都看不到,例如:

    processlist

    总结

    实际上 CPU 100% 的问题其实不仅仅是单纯的 %us,还会有 %io,%sys 等,这些会涉及到 MySQL 与 Linux 相关联的一部分内容,展开来就会比较多了。本文仅从 %us 出发尝试梳理一下排查&定位的思路和方法,在分析 %io,%sys 等方面的问题时,也可以用类似的思路,从这些指标的意义开始,结合 MySQL 的一些特性或者特点,逐步理清楚表象背后的原因。

    实战体验几种MySQLCluster方案_MySQL


    1.背景
    MySQL的cluster方案有很多官方和第三方的选择,选择多就是一种烦恼,因此,我们考虑MySQL数据库满足下三点需求,考察市面上可行的解决方案:

    高可用性:主服务器故障后可自动切换到后备服务器可伸缩性:可方便通过脚本增加DB服务器负载均衡:支持手动把某公司的数据请求切换到另外的服务器,可配置哪些公司的数据服务访问哪个服务器
    需要选用一种方案满足以上需求。在MySQL官方网站上参考了几种解决方案的优缺点:



    综合考虑,决定采用MySQL Fabric和MySQL Cluster方案,以及另外一种较成熟的集群方案Galera Cluster进行预研。

    2.MySQLCluster
    简介:

    MySQL Cluster 是MySQL 官方集群部署方案,它的历史较久。支持通过自动分片支持读写扩展,通过实时备份冗余数据,是可用性最高的方案,声称可做到99.999%的可用性。

    架构及实现原理:



    MySQL cluster主要由三种类型的服务组成:

    NDB Management Server:管理服务器主要用于管理cluster中的其他类型节点(Data Node和SQL Node),通过它可以配置Node信息,启动和停止Node。 SQL Node:在MySQL Cluster中,一个SQL Node就是一个使用NDB引擎的mysql server进程,用于供外部应用提供集群数据的访问入口。Data Node:用于存储集群数据;系统会尽量将数据放在内存中。


    缺点及*:

    对需要进行分片的表需要修改引擎Innodb为NDB,不需要分片的可以不修改。NDB的事务隔离级别只支持Read Committed,即一个事务在提交前,查询不到在事务内所做的修改;而Innodb支持所有的事务隔离级别,默认使用Repeatable Read,不存在这个问题。外键支持:虽然最新的Cluster版本已经支持外键,但性能有问题(因为外键所关联的记录可能在别的分片节点中),所以建议去掉所有外键。Data Node节点数据会被尽量放在内存中,对内存要求大。
    数据库系统提供了四种事务隔离级别:
    A.Serializable(串行化):一个事务在执行过程中完全看不到其他事务对数据库所做的更新(事务执行的时候不允许别的事务并发执行。事务串行化执行,事务只能一个接着一个地执行,而不能并发执行。)。
    B.Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但是不能看到其他其他事务对已有记录的更新。
    C.Read Commited(读已提交数据):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且能看到其他事务已经提交的对已有记录的更新。
    D.Read Uncommitted(读未提交数据):一个事务在执行过程中可以看到其他事务没有提交的新插入的记录,而且能看到其他事务没有提交的对已有记录的更新。

    3.MySQL Fabric
    简介:

    为了实现和方便管理MySQL 分片以及实现高可用部署,Oracle在2014年5月推出了一套为各方寄予厚望的MySQL产品 -- MySQL Fabric, 用来管理MySQL 服务,提供扩展性和容易使用的系统,Fabric当前实现了两个特性:高可用和使用数据分片实现可扩展性和负载均衡,这两个特性能单独使用或结合使用。

    MySQL Fabric 使用了一系列的python脚本实现。

    应用案例:由于该方案在去年才推出,目前在网上暂时没搜索到有大公司的应用案例。

    架构及实现原理:

    Fabric支持实现高可用性的架构图如下:

    Fabric使用HA组实现高可用性,其中一台是主服务器,其他是备份服务器, 备份服务器通过同步复制实现数据冗余。应用程序使用特定的驱动,连接到Fabric 的Connector组件,当主服务器发生故障后,Connector自动升级其中一个备份服务器为主服务器,应用程序无需修改。
    Fabric支持可扩展性及负载均衡的架构如下:





    使用多个HA 组实现分片,每个组之间分担不同的分片数据(组内的数据是冗余的,这个在高可用性中已经提到)
    应用程序只需向connector发送query和insert等语句,Connector通过MasterGroup自动分配这些数据到各个组,或从各个组中组合符合条件的数据,返回给应用程序。
    缺点及*:
    影响比较大的两个*是:

    自增长键不能作为分片的键;事务及查询只支持在同一个分片内,事务中更新的数据不能跨分片,查询语句返回的数据也不能跨分片。


    测试高可用性

    服务器架构:



    功能



    IP



    Port





    Backing store(保存各服务器配置信息)



    200.200.168.24



    3306





    Fabric 管理进程(Connector)



    200.200.168.24



    32274





    HA Group 1 -- Master



    200.200.168.23



    3306





    HA Group 1 -- Slave



    200.200.168.25



    3306



    安装过程省略,下面讲述如何设置高可用组、添加备份服务器等过程

    首先,创建高可用组,例如组名group_id-1,命令:

    mysqlfabric group create group_id-1

    往组内group_id-1添加机器200.200.168.25和200.200.168.23:

    mysqlfabric group add group_id-1 200.200.168.25:3306

    mysqlfabric group add group_id-1 200.200.168.23:3306

    然后查看组内机器状态:



    由于未设置主服务器,两个服务的状态都是SECONDARY
    提升其中一个为主服务器:
    mysqlfabric group promote group_id-1 --slave_id 00f9831f-d602-11e3-b65e-0800271119cb
    然后再查看状态:



    设置成主服务器的服务已经变成Primary。
    另外,mode属性表示该服务器是可读写(READ_WRITE),或只读(READ_ONLY),只读表示可以分摊查询数据的压力;只有主服务器能设置成可读写(READ_WRITE)。
    这时检查25服务器的slave状态:



    可以看到它的主服务器已经指向23
    然后激活故障自动切换功能:
    mysqlfabric group activate group_id-1
    激活后即可测试服务的高可以性
    首先,进行状态测试:
    停止主服务器23



    然后查看状态:



    可以看到,这时将25自动提升为主服务器。
    但如果将23恢复起来后,需要手动重新设置23为主服务器。
    实时性测试:
    目的:测试在主服务更新数据后,备份服务器多久才显示这些数据
    测试案例:使用java代码建连接,往某张表插入100条记录,看备份服务器多久才能同步这100条数据
    测试结果:
    表中原来有101条数据,运行程序后,查看主服务器的数据条数:



    可见主服务器当然立即得到更新。
    查看备份服务器的数据条数:



    但备份服务器等待了1-2分钟才同步完成(可以看到fabric使用的是异步复制,这是默认方式,性能较好,主服务器不用等待备份服务器返回,但同步速度较慢)

    对于从服务器同步数据稳定性问题,有以下解决方案:

    使用半同步加强数据一致性:异步复制能提供较好的性能,但主库只是把binlog日志发送给从库,动作就结束了,不会验证从库是否接收完毕,风险较高。半同步复制会在发送给从库后,等待从库发送确认信息后才返回。可以设置从库中同步日志的更新方式,从而减少从库同步的延迟,加快同步速度。 安装半同步复制:
    在mysql中运行
    install plugin rpl_semi_sync_master soname 'semisync_master.so';
    install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
    SET GLOBAL rpl_semi_sync_master_enabled=ON;
    SET GLOBAL rpl_semi_sync_slave_enabled=ON;
    修改my.cnf :
    rpl_semi_sync_master_enabled=1
    rpl_semi_sync_slave_enabled=1
    sync_relay_log=1
    sync_relay_log_info=1
    sync_master_info=1
    稳定性测试:
    测试案例:使用java代码建连接,往某张表插入1w条记录,插入过程中将其中的master服务器停了,看备份服务器是否有这1w笔记录
    测试结果,停止主服务器后,java程序抛出异常:


    但这时再次发送sql命令,可以成功返回。证明只是当时的事务失败了。连接切换到了备份服务器,仍然可用。
    翻阅了mysql文档,有章节说明了这个问题:



    里面提到:当主服务器当机时,我们的应用程序虽然是不需做任何修改的,但在主服务器被备份服务器替换前,某些事务会丢失,这些可以作为正常的mysql错误来处理。
    数据完整性校验:
    测试主服务器停止后,备份服务器是否能够同步所有数据。
    重启了刚才停止主服务器后,查看记录数



    可以看到在插入1059条记录后被停止了。

    现在看看备份服务器的记录数是多少,看看在主服务器当机后是否所有数据都能同步过来



    大约经过了几十秒,才同步完,数据虽然不是立即同步过来,但没有丢失。

    1.2、分片:如何支持可扩展性和负载均衡

    fabric分片简介:当一台机器或一个组承受不了服务压力后,可以添加服务器分摊读写压力,通过Fabirc的分片功能可以将某些表中数据分散存储到不同服务器。我们可以设定分配数据存储的规则,通过在表中设置分片key设置分配的规则。另外,有些表的数据可能并不需要分片存储,需要将整张表存储在同一个服务器中,可以将设置一个全局组(Global Group)用于存储这些数据,存储到全局组的数据会自动拷贝到其他所有的分片组中。



    4.Galera Cluster
    简介:

    Galera Cluster号称是世界上最先进的开源数据库集群方案



    主要优点及特性:

    真正的多主服务模式:多个服务能同时被读写,不像Fabric那样某些服务只能作备份用同步复制:无延迟复制,不会产生数据丢失热备用:当某台服务器当机后,备用服务器会自动接管,不会产生任何当机时间自动扩展节点:新增服务器时,不需手工复制数据库到新的节点支持InnoDB引擎对应用程序透明:应用程序不需作修改


    架构及实现原理:
    首先,我们看看传统的基于mysql Replication(复制)的架构图:



    Replication方式是通过启动复制线程从主服务器上拷贝更新日志,让后传送到备份服务器上执行,这种方式存在事务丢失及同步不及时的风险。Fabric以及传统的主从复制都是使用这种实现方式。

    而Galera则采用以下架构保证事务在所有机器的一致性:



    客户端通过Galera Load Balancer访问数据库,提交的每个事务都会通过wsrep API 在所有服务器中执行,要不所有服务器都执行成功,要不就所有都回滚,保证所有服务的数据一致性,而且所有服务器同步实时更新。
    缺点及*:

    由于同一个事务需要在集群的多台机器上执行,因此网络传输及并发执行会导致性能上有一定的消耗。所有机器上都存储着相同的数据,全冗余。若一台机器既作为主服务器,又作为备份服务器,出现乐观锁导致rollback的概率会增大,编写程序时要小心。不支持的SQL:LOCK / UNLOCK TABLES / GET_LOCK(), RELEASE_LOCK()…不支持XA Transaction
    目前基于Galera Cluster的实现方案有三种:Galera Cluster for MySQL、Percona XtraDB Cluster、MariaDB Galera Cluster。
    我们采用较成熟、应用案例较多的Percona XtraDB Cluster。
    应用案例:
    超过2000多家外国企业使用:


    包括:

    集群部署架构:



    功能



    IP



    Port





    Backing store(保存各服务器配置信息)



    200.200.168.24



    3306





    Fabric 管理进程(Connector)



    200.200.168.24



    32274





    HA Master 1



    200.200.168.24



    3306





    HA Master 2



    200.200.168.25



    3306





    HA Master 3



    200.200.168.23



    3306



    4.1、测试数据同步

    在机器24上创建一个表:



    立即在25 中查看,可见已被同步创建



    使用Java代码在24服务器上插入100条记录



    立即在25服务器上查看记录数



    可见数据同步是立即生效的。
    4.2、测试添加集群节点
    添加一个集群节点的步骤很简单,只要在新加入的机器上部署好Percona XtraDB Cluster,然后启动,系统将自动将现存集群中的数据同步到新的机器上。
    现在为了测试,先将其中一个节点服务停止:



    然后使用java代码在集群上插入100W数据



    查看100w数据的数据库大小:



    这时启动另外一个节点,启动时即会自动同步集群的数据:



    启动只需20秒左右,查看数据大小一致,查看表记录数,也已经同步过来



    5.对比总结





    MySQL Fabric



    Galera Cluster





    使用案例



    2014年5月才推出,目前在网上暂时没搜索到有大公司的应用案例



    方案较成熟,外国多家互联网公司使用





    数据备份的实时性



    由于使用异步复制,一般延时几十秒,但数据不会丢失。



    实时同步,数据不会丢失





    数据冗余



    使用分片,通过设置分片key规则可以将同一张表的不同数据分散在多台机器中



    每个节点全冗余,没有分片





    高可用性



    通过Fabric Connector实现主服务器当机后的自动切换,但由于备份延迟,切换后可能不能立即查询数据



    使用HAProxy实现。由于实时同步,切换的可用性更高。





    可伸缩性



    添加节点后,需要先手工复制集群数据



    扩展节点十分方便,启动节点时自动同步集群数据,100w数据(100M)只需20秒左右





    负载均衡



    通过HASharding实现



    使用HAProxy实现负载均衡





    程序修改



    需要切换成jdbc:mysql:fabric的jdbc类和url



    程序无需修改





    性能对比



    使用java直接用jdbc插入100条记录,大概2000+ms



    跟直接操作mysql一样,直接用jdbc插入100条记录,大概600ms



    6.实践应用
    综合考虑上面方案的优缺点,我们比较偏向选择Galera 如果只有两台数据库服务器,考虑采用以下数据库架构实现高可用性、负载均衡和动态扩展:



    如果三台机器可以考虑:



    实战体验几种MySQLCluster方案_MySQL


    1.背景
    MySQL的cluster方案有很多官方和第三方的选择,选择多就是一种烦恼,因此,我们考虑MySQL数据库满足下三点需求,考察市面上可行的解决方案:

    高可用性:主服务器故障后可自动切换到后备服务器可伸缩性:可方便通过脚本增加DB服务器负载均衡:支持手动把某公司的数据请求切换到另外的服务器,可配置哪些公司的数据服务访问哪个服务器
    需要选用一种方案满足以上需求。在MySQL官方网站上参考了几种解决方案的优缺点:



    综合考虑,决定采用MySQL Fabric和MySQL Cluster方案,以及另外一种较成熟的集群方案Galera Cluster进行预研。

    2.MySQLCluster
    简介:

    MySQL Cluster 是MySQL 官方集群部署方案,它的历史较久。支持通过自动分片支持读写扩展,通过实时备份冗余数据,是可用性最高的方案,声称可做到99.999%的可用性。

    架构及实现原理:



    MySQL cluster主要由三种类型的服务组成:

    NDB Management Server:管理服务器主要用于管理cluster中的其他类型节点(Data Node和SQL Node),通过它可以配置Node信息,启动和停止Node。 SQL Node:在MySQL Cluster中,一个SQL Node就是一个使用NDB引擎的mysql server进程,用于供外部应用提供集群数据的访问入口。Data Node:用于存储集群数据;系统会尽量将数据放在内存中。


    缺点及*:

    对需要进行分片的表需要修改引擎Innodb为NDB,不需要分片的可以不修改。NDB的事务隔离级别只支持Read Committed,即一个事务在提交前,查询不到在事务内所做的修改;而Innodb支持所有的事务隔离级别,默认使用Repeatable Read,不存在这个问题。外键支持:虽然最新的Cluster版本已经支持外键,但性能有问题(因为外键所关联的记录可能在别的分片节点中),所以建议去掉所有外键。Data Node节点数据会被尽量放在内存中,对内存要求大。
    数据库系统提供了四种事务隔离级别:
    A.Serializable(串行化):一个事务在执行过程中完全看不到其他事务对数据库所做的更新(事务执行的时候不允许别的事务并发执行。事务串行化执行,事务只能一个接着一个地执行,而不能并发执行。)。
    B.Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但是不能看到其他其他事务对已有记录的更新。
    C.Read Commited(读已提交数据):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且能看到其他事务已经提交的对已有记录的更新。
    D.Read Uncommitted(读未提交数据):一个事务在执行过程中可以看到其他事务没有提交的新插入的记录,而且能看到其他事务没有提交的对已有记录的更新。

    3.MySQL Fabric
    简介:

    为了实现和方便管理MySQL 分片以及实现高可用部署,Oracle在2014年5月推出了一套为各方寄予厚望的MySQL产品 -- MySQL Fabric, 用来管理MySQL 服务,提供扩展性和容易使用的系统,Fabric当前实现了两个特性:高可用和使用数据分片实现可扩展性和负载均衡,这两个特性能单独使用或结合使用。

    MySQL Fabric 使用了一系列的python脚本实现。

    应用案例:由于该方案在去年才推出,目前在网上暂时没搜索到有大公司的应用案例。

    架构及实现原理:

    Fabric支持实现高可用性的架构图如下:

    Fabric使用HA组实现高可用性,其中一台是主服务器,其他是备份服务器, 备份服务器通过同步复制实现数据冗余。应用程序使用特定的驱动,连接到Fabric 的Connector组件,当主服务器发生故障后,Connector自动升级其中一个备份服务器为主服务器,应用程序无需修改。
    Fabric支持可扩展性及负载均衡的架构如下:





    使用多个HA 组实现分片,每个组之间分担不同的分片数据(组内的数据是冗余的,这个在高可用性中已经提到)
    应用程序只需向connector发送query和insert等语句,Connector通过MasterGroup自动分配这些数据到各个组,或从各个组中组合符合条件的数据,返回给应用程序。
    缺点及*:
    影响比较大的两个*是:

    自增长键不能作为分片的键;事务及查询只支持在同一个分片内,事务中更新的数据不能跨分片,查询语句返回的数据也不能跨分片。


    测试高可用性

    服务器架构:



    功能



    IP



    Port





    Backing store(保存各服务器配置信息)



    200.200.168.24



    3306





    Fabric 管理进程(Connector)



    200.200.168.24



    32274





    HA Group 1 -- Master



    200.200.168.23



    3306





    HA Group 1 -- Slave



    200.200.168.25



    3306



    安装过程省略,下面讲述如何设置高可用组、添加备份服务器等过程

    首先,创建高可用组,例如组名group_id-1,命令:

    mysqlfabric group create group_id-1

    往组内group_id-1添加机器200.200.168.25和200.200.168.23:

    mysqlfabric group add group_id-1 200.200.168.25:3306

    mysqlfabric group add group_id-1 200.200.168.23:3306

    然后查看组内机器状态:



    由于未设置主服务器,两个服务的状态都是SECONDARY
    提升其中一个为主服务器:
    mysqlfabric group promote group_id-1 --slave_id 00f9831f-d602-11e3-b65e-0800271119cb
    然后再查看状态:



    设置成主服务器的服务已经变成Primary。
    另外,mode属性表示该服务器是可读写(READ_WRITE),或只读(READ_ONLY),只读表示可以分摊查询数据的压力;只有主服务器能设置成可读写(READ_WRITE)。
    这时检查25服务器的slave状态:



    可以看到它的主服务器已经指向23
    然后激活故障自动切换功能:
    mysqlfabric group activate group_id-1
    激活后即可测试服务的高可以性
    首先,进行状态测试:
    停止主服务器23



    然后查看状态:



    可以看到,这时将25自动提升为主服务器。
    但如果将23恢复起来后,需要手动重新设置23为主服务器。
    实时性测试:
    目的:测试在主服务更新数据后,备份服务器多久才显示这些数据
    测试案例:使用java代码建连接,往某张表插入100条记录,看备份服务器多久才能同步这100条数据
    测试结果:
    表中原来有101条数据,运行程序后,查看主服务器的数据条数:



    可见主服务器当然立即得到更新。
    查看备份服务器的数据条数:



    但备份服务器等待了1-2分钟才同步完成(可以看到fabric使用的是异步复制,这是默认方式,性能较好,主服务器不用等待备份服务器返回,但同步速度较慢)

    对于从服务器同步数据稳定性问题,有以下解决方案:

    使用半同步加强数据一致性:异步复制能提供较好的性能,但主库只是把binlog日志发送给从库,动作就结束了,不会验证从库是否接收完毕,风险较高。半同步复制会在发送给从库后,等待从库发送确认信息后才返回。可以设置从库中同步日志的更新方式,从而减少从库同步的延迟,加快同步速度。 安装半同步复制:
    在mysql中运行
    install plugin rpl_semi_sync_master soname 'semisync_master.so';
    install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
    SET GLOBAL rpl_semi_sync_master_enabled=ON;
    SET GLOBAL rpl_semi_sync_slave_enabled=ON;
    修改my.cnf :
    rpl_semi_sync_master_enabled=1
    rpl_semi_sync_slave_enabled=1
    sync_relay_log=1
    sync_relay_log_info=1
    sync_master_info=1
    稳定性测试:
    测试案例:使用java代码建连接,往某张表插入1w条记录,插入过程中将其中的master服务器停了,看备份服务器是否有这1w笔记录
    测试结果,停止主服务器后,java程序抛出异常:


    但这时再次发送sql命令,可以成功返回。证明只是当时的事务失败了。连接切换到了备份服务器,仍然可用。
    翻阅了mysql文档,有章节说明了这个问题:



    里面提到:当主服务器当机时,我们的应用程序虽然是不需做任何修改的,但在主服务器被备份服务器替换前,某些事务会丢失,这些可以作为正常的mysql错误来处理。
    数据完整性校验:
    测试主服务器停止后,备份服务器是否能够同步所有数据。
    重启了刚才停止主服务器后,查看记录数



    可以看到在插入1059条记录后被停止了。

    现在看看备份服务器的记录数是多少,看看在主服务器当机后是否所有数据都能同步过来



    大约经过了几十秒,才同步完,数据虽然不是立即同步过来,但没有丢失。

    1.2、分片:如何支持可扩展性和负载均衡

    fabric分片简介:当一台机器或一个组承受不了服务压力后,可以添加服务器分摊读写压力,通过Fabirc的分片功能可以将某些表中数据分散存储到不同服务器。我们可以设定分配数据存储的规则,通过在表中设置分片key设置分配的规则。另外,有些表的数据可能并不需要分片存储,需要将整张表存储在同一个服务器中,可以将设置一个全局组(Global Group)用于存储这些数据,存储到全局组的数据会自动拷贝到其他所有的分片组中。



    4.Galera Cluster
    简介:

    Galera Cluster号称是世界上最先进的开源数据库集群方案



    主要优点及特性:

    真正的多主服务模式:多个服务能同时被读写,不像Fabric那样某些服务只能作备份用同步复制:无延迟复制,不会产生数据丢失热备用:当某台服务器当机后,备用服务器会自动接管,不会产生任何当机时间自动扩展节点:新增服务器时,不需手工复制数据库到新的节点支持InnoDB引擎对应用程序透明:应用程序不需作修改


    架构及实现原理:
    首先,我们看看传统的基于mysql Replication(复制)的架构图:



    Replication方式是通过启动复制线程从主服务器上拷贝更新日志,让后传送到备份服务器上执行,这种方式存在事务丢失及同步不及时的风险。Fabric以及传统的主从复制都是使用这种实现方式。

    而Galera则采用以下架构保证事务在所有机器的一致性:



    客户端通过Galera Load Balancer访问数据库,提交的每个事务都会通过wsrep API 在所有服务器中执行,要不所有服务器都执行成功,要不就所有都回滚,保证所有服务的数据一致性,而且所有服务器同步实时更新。
    缺点及*:

    由于同一个事务需要在集群的多台机器上执行,因此网络传输及并发执行会导致性能上有一定的消耗。所有机器上都存储着相同的数据,全冗余。若一台机器既作为主服务器,又作为备份服务器,出现乐观锁导致rollback的概率会增大,编写程序时要小心。不支持的SQL:LOCK / UNLOCK TABLES / GET_LOCK(), RELEASE_LOCK()…不支持XA Transaction
    目前基于Galera Cluster的实现方案有三种:Galera Cluster for MySQL、Percona XtraDB Cluster、MariaDB Galera Cluster。
    我们采用较成熟、应用案例较多的Percona XtraDB Cluster。
    应用案例:
    超过2000多家外国企业使用:


    包括:

    集群部署架构:



    功能



    IP



    Port





    Backing store(保存各服务器配置信息)



    200.200.168.24



    3306





    Fabric 管理进程(Connector)



    200.200.168.24



    32274





    HA Master 1



    200.200.168.24



    3306





    HA Master 2



    200.200.168.25



    3306





    HA Master 3



    200.200.168.23



    3306



    4.1、测试数据同步

    在机器24上创建一个表:



    立即在25 中查看,可见已被同步创建



    使用Java代码在24服务器上插入100条记录



    立即在25服务器上查看记录数



    可见数据同步是立即生效的。
    4.2、测试添加集群节点
    添加一个集群节点的步骤很简单,只要在新加入的机器上部署好Percona XtraDB Cluster,然后启动,系统将自动将现存集群中的数据同步到新的机器上。
    现在为了测试,先将其中一个节点服务停止:



    然后使用java代码在集群上插入100W数据



    查看100w数据的数据库大小:



    这时启动另外一个节点,启动时即会自动同步集群的数据:



    启动只需20秒左右,查看数据大小一致,查看表记录数,也已经同步过来



    5.对比总结





    MySQL Fabric



    Galera Cluster





    使用案例



    2014年5月才推出,目前在网上暂时没搜索到有大公司的应用案例



    方案较成熟,外国多家互联网公司使用





    数据备份的实时性



    由于使用异步复制,一般延时几十秒,但数据不会丢失。



    实时同步,数据不会丢失





    数据冗余



    使用分片,通过设置分片key规则可以将同一张表的不同数据分散在多台机器中



    每个节点全冗余,没有分片





    高可用性



    通过Fabric Connector实现主服务器当机后的自动切换,但由于备份延迟,切换后可能不能立即查询数据



    使用HAProxy实现。由于实时同步,切换的可用性更高。





    可伸缩性



    添加节点后,需要先手工复制集群数据



    扩展节点十分方便,启动节点时自动同步集群数据,100w数据(100M)只需20秒左右





    负载均衡



    通过HASharding实现



    使用HAProxy实现负载均衡





    程序修改



    需要切换成jdbc:mysql:fabric的jdbc类和url



    程序无需修改





    性能对比



    使用java直接用jdbc插入100条记录,大概2000+ms



    跟直接操作mysql一样,直接用jdbc插入100条记录,大概600ms



    6.实践应用
    综合考虑上面方案的优缺点,我们比较偏向选择Galera 如果只有两台数据库服务器,考虑采用以下数据库架构实现高可用性、负载均衡和动态扩展:



    如果三台机器可以考虑:



    程序员工作总结

      程序员是从事程序开发、程序维护的专业人员。以下是我整理的程序员工作总结,希望对大家有帮助!

      程序员工作总结1

      光阴如梭,一年的工作转瞬即将成为历史,伴随着新年钟声的临近,我们依依惜别硕果累累的20xx年,满怀热情的迎来即将到来的20xx年。在这年终之际,现对我来公司这几个月的时间里,总结自己所做的工作,分析在工作中的得与失,现汇报如下:

      20xx年的六月份,我带着好奇而欢快的心情来到我心目中向往的神圣之地北京。这是我毕业后第一个目标,来北京发展。我离开了我上学的原始领域,和我的同学们踏入北京之地。说句好听的,我的技术生涯还是很幸运的,当然这是我相对于留守本地找工作的同学来说的,面对高昂的学费和残酷的社会现实,选择本专业就业还是有一定困难的,在北京中关村混了几个月后,幸运地找到了我人生的第一份工作,做Java程序的工作。也就是来到咱们公司—北京联合兴辰。

      来到贵公司,学了半个皮毛的MVC和SSH的我有了份工作,我感到十分的庆幸,也承担了第一个项目,能一个人自主开发的项目。在这里,终于能够将学到的那点东西派上用场。从技术的角度来讲,20xx年我的关键词就是SSH,其次就是Hibernate。

      这几个月淡淡无奇,学到的东西很多,有框架上的、Mysql数据库的,等等,但是也都是在皮毛上的,掌握着能熟练使用而已。首先,做程序员的要记住第一条经验:“学历代表过去、能力代表现在、学习代表未来。”我个人觉得学历并不代表全部,我们每天都可以学到新的知识,知识是可以一点点积累的,只要肯努力,一切皆有可能.其次,一定要确定自己的发展方向,并为此目的制定可行的计划。不要说什么,“我刚毕业,还不知道将来可能做什么?”“跟着感觉走,先做做看”。因为,这样的观点会通过你的潜意识去暗示你的行为无所事事、碌碌无为。一直做技术,将来成为专家级人物?向管理方向走,成为职业经理人?先熟悉行业和领域,将来自立门户?还是先在行业里面混混,过几年转行做点别的?这很重要,这是你值得深思的问题,它将决定你近几年、十年内“做什么事情才是在做正确的事情!。”

      软件开发团队中,技术不是万能的,但没有技术是万万不能的!在技术型团队中,技术与人品同等重要,当然长相也比较重要么。在软件项目团队中,技术水平是受人重视和尊重的重要砝码。无论你是做ERP、管理、系统分析、设计、编码,还是产品管理、测试、文档、实施、维护,多少你都要有技术基础。但是你没有这方面的基础是万万不能胜任你的工作的详细制定自己软件开发专业知识学习计划,并注意及时修正和调整(软件开发技术变化实在太快)。请牢记:“如果一个软件开发人员在1、2年内都没有更新过自己的知识,那么,其实他已经不再属于这个行业了。”

      不要告诉自己没有时间。时间就像海绵里的水,多学一些技能对于我们来说亏不到自己,我们的工作从学而来,就是靠着每天的学习,交流,做人中得到书籍是人类进步的阶梯,对软件开发人员尤其如此。我的项目经理经常说,趁着自己还年轻,花几个钱买书看看,书籍是学习知识的ZUI有效途径,不要过多地指望在工作中能遇到“世外高人”,并不厌其烦地教你。只有通过自学将书本变成的自己智慧,才算是真正拥有了它。不要仅局限于对某项技术的表面使用上,哪怕你只是偶尔用一、二次。

      对于一个做程序的,试试学习其领域的相关知识点,对各个平台都要了解,向什么JavaEE,J2ME,JavaSE,VB,VCC#,C++这些程序啊,也要试着去了解他们,虽然程序的套路基本是差不多的,但是也各有千秋的,我是学Java的,当然Java很强大,我就很爱Google出的那个安卓系统,Java实在太牛啦!不得不惊叹,例如我没有事的时候也因该提醒自己学习一些JBoss、Spring、Hibernate等等优秀的开源产品或者框架,抽空看看大师们是如何抽象、分析、设计和实现那些类似问题的通用解决方案的。试着研究一下jar包,知道每个jar的功能和实现的方法,免得自己以后的工作遇到一些让你不明就里、一头雾水的问题,因为,很多东西你“知其然且知其所以然”!在一种语言上编程,但别为其束缚了思想。“代码大全”中说:“深入一门语言编程,不要浮于表面”。深入一门语言开发还远远不足,任何编程语言的存在都有其自身的理由。

      有时候咱们会遇到一些问题,你单纯的用着一种方法有时候会解决不了问题,或者遇到问题卡在那里啦,这是你需要的是灵感。灵感来自那里,你可以借鉴Spring、Hibernate、JBoss等等优秀的开源框架的设计思想,你可以参照Java的IoC、AOP的设计思路,你可以从其他语言的程序中借鉴他们的套路,这就是我们的灵感,俗话说“他山之石、可以攻玉”。养成总结与反思的习惯,并有意识地提炼日常工作成果,形成自己的个人源码库、解决某类问题的通用系统体系结构、甚至进化为框架。我们在做程序的时候,别人为什么要提示你把每个方法都要写上注释,注释这段代码是干什么的,这是做好一个程序员基本的要诀,这就是你的基本功,当然在写代码的时候也不是都是有用的代码,有些功能是可以通用的,咱们为什么不可以给他打包封装jar,将来或者以后会用到呢,为什么会有那么多很牛的框架,这些都是程序员们提炼出来的,形成一整套的代码结构和体系,被人用的时候感觉非常好用,我们目前写不了这么牛的程序,但是还是可以形成自己的个人源码库的。

      心态有多开放,视野就有多开阔。不要抱着自己的技术和成果,等到它们都已经过时变成垃圾了,才拿出来丢人现眼。请及时发布自己的研究成果。例如你在网上看到别人遇到问题,这个问题可能你之前也遇到啦,不要抱着你那自私的心态,背后说“累死你,自己去找吧,小样“,建议大家,上你的CSDN号,我感觉这个东东很不错,技术交流。咱们“与人交换苹果之后,每个人还是只有一个苹果;但交换思想之后,每个人都拥有两种思想”,道理大家都懂,但有多少人真正能做到呢?我的反思不要去做技术上的高手,学会做人。提高自己的专业技能,能胜任工作。

      提高软件知识和技术只是问题的表面,本质是要提高自己认识问题、分析问题、解决问题的思想高度。在能胜任工作的基础上,立即去涉猎其它领域的专业知识,丰富自己的知识体系、提高自己的综合素质,尤其是那些目标不在技术方面的朋友。这也是本人的目标,再接再厉吧!

      程序员工作总结2

      时间一晃而过,转眼间到公司已经半年多了。这是我人生中弥足珍贵的一段经历。在这段时间里各级领导在工作上给予了我极大的帮助,在生活上给予了我极大的关心,让我充分感受到了领导们“海纳百川”的`胸襟,感受到了大发人“不经历风雨,怎能见彩虹”的豪气。在对公司各级领导肃然起敬的同时,也为我有机会成为公司的一份子而自豪。在这半年多的时间里,在领导和同事们的悉心关怀和指导下,通过自身的努力,各方面均取得了一定的进步,现将我的工作情况作如下汇报。

      一、通过培训学习和日常工作积累使我对公司有了一定的新的认识。在5月中旬我来到了公司信息科技有限公司参加招聘,经过几轮面试和笔试,终于能够有幸加入了公司,在我进入公司时我拿到的第一份资料就是公司介绍和新员工入职说明,当时只是觉得公司很正规,很强大。在和部门领导以及项目经理交流后,感觉公司很亲切,很温馨。对其它方面就不太知道了,特别是对视频监控几乎一无所知。通过三个月的亲身体会,对智能交通和公司有了一定了解。

      公司的理念在平时的工作以及项目开发时体现的淋漓尽致,本人对公司的理念非常认同。公司发展不忘回报社会的壮举,令人敬佩。公司以人为本、尊重人才的思想在实际工作中贯彻,这是公司能发展壮大的重要原因。在十年左右的时间实现跨越发展的确很不容易,在智能交通行业深入发展是公司的雄心壮志,也是凝聚人才的核心动力。现在公司在视频监控以及安防行业起到了举足轻重的地位,今后还将更加辉煌。

      二、遵守各项规章制度,认真工作,使自己素养不断得到提高。爱岗敬业的职业道德素质是每一项工作顺利开展并最终取得成功的保障。在这半年多的时间里,我能遵守公司的各项规章制度,兢兢业业做好本职业工作,半年来从未迟到早退,用满腔热情积极、认真地完成好每一项任务,认真履行岗位职责,平时生活中团结同事、不断提升自己的团队合作精神。一本《细节决定成败》让我豪情万丈,一种积极豁达的心态、一种良好的习惯、一份计划并按时完成竟是如此重要,并最终决定一个的人成败。这本书让我对自己的人生有了进一步的认识,渴望有所突破的我,将会在以后的工作和生活中时时提醒自己,以便自己以后的人生道路越走越精彩。

      三、认真学习岗位职能,工作能力得到了一定的提高。根据目前工作分工,我的主要工作任务是:

      (1)参与公司软件项目的开发与测试;

      (2)负责安徽省路警联合指挥中心软件系统的维护工作。通过完成上述工作,使我认识到一个称职的开发人员应当具有良好的语言表达能力、扎实的技术能力、较强的逻辑处理能力、灵活的应变问题能力、有效的对外联系能力。在参与项目开发的过程中,发现很多看似简单的工作,其实里面还有很多技巧。

      四、不足和需改进方面。

      虽然加入公司这个大家庭已经半年有余,对开发技术掌握的还不是很深,对发现问题的处理还不是很全面,对分工的工作还没有形成系统的计划。随着对公司和工作的进一步熟悉,我也希望能够在今后的工作中更加迅速的提升自己的业务能力以及技术能力,我觉得多做一些工作更能体现自己的人生价值。“业精于勤而荒于嬉”,在以后的工作中我要不断学习业务知识,通过多看、多问、多学、多练来不断的提高自己的各项业务技能。学无止境,时代的发展瞬息万变,各种学科知识日新月异。我将坚持不懈地努力学习各种知识,并用于指导实践。在今后工作中,要努力做好开发人员的本职工作,把自己的工作创造性做好做扎实,为项目的开发以及公司的发展贡献自己的力量。

      程序员工作总结3

      我是一名程序员,在过去的一年里,软件研发部团结协作,以及在公司这充满奋斗的环境下,我以严肃认真的工作态度和百折不饶的精神,努力的完成了公司的各项工作,在软件研发、团队协作和个人成长上也取得了一定的成绩。在公司一年的工作已经结束,特向公司总结汇报如下:

       一、软件研发

      根据公司的安排,项目的需要。在自身的努力、伍经理的帮组,团队的合作下,克服重重技术困难,增长了工作经验,收获丰盈:

      1、asp开发

      以前我在其他公司也做过一些开发,但是底层和架构与页面样式我都是没有涉及到的。通过这一年在本公司的的这些项目程序中的锻炼,我成长了,我学会了很多很多。

      首先,面向对象语言的收获。对于当前编程的主流思想是对象,任何事物都可以用对象来表示。以前理解这些话很费解都是从表面上理解,没有从中的体会,通过这次asp项目的开发,不管是数据还是外部一些条件我们都可以抽象成对象,都可以用对象来表示,具体可以用语言中的类方等。asp如此,c#如此java也同样如此。

      其次,具备独立完成vb知识方面的能力。以前没有做过vb的东西,加上这次asp的做,这次涉及到的领域也非常广,常用的重要的都有涉及,并且还补充xml,java实际操作中空白的部分。通过这一年的开发,我能胜任这方面的工作,能独立完成这方面的工作。

      再次,c#方面存在一些不足。LocALhOST通过c#这次软件的开发,也发现自己的不足,如基础知识掌握不牢,缺乏编程整体思想。这些都是需要在工作中完善和改进的。

      2、数据库开发

      数据库是伴随着项目以来用的最多最平凡的技术。以前对数据库只是会一些简单常用的操作,经过这一年项目的实战,对数据库的操作增加了一些丰富的经验。为以后的工作和经验的积累都奠定了坚实的基础。同时在项目中还用到了oracel与access数据库,这是我的收获。

      优点:

      能熟练的运用数据库技术进行开发。特别是对sql数据库的操作,经过这么长时间的积累,基本上能合理的设计和新建数据库,同时在数据结构上也加强了对数据库的理解。通过项目的实践现在能熟练使用和编写多种sql语句。还掌握了一些关于数据库优化sql语句优化的方法,能进行一些简单的优化。

      缺点:

      数据是一门比较先进的技术,并不是你会写一些sql语句,能建几个数据库你就是数据库工程师。要成为一个好的数据库管理员是要经过长时间的工作积累。针对自己的不足,在以后的工作和学习中多接触,多运用新的知识点。充实自己的经验和知识储备。

       二、团队协作

      上面的成功与收获,除了自身努力外,以及公司的支持。是这个团队铸造了我。我们这个团队也是因为有了我们这些拼搏协作的队员,使得它成为一个具有务实、拼搏、创新精神的团队。我与软件研发小组是一个整体,这里的团队总结也就是我在这个团队中的收获。

      务实:公司下发的任务,下发的工作,件件都是用心去做的。我们这个团队中没有一个人在工作的时候做了工作以外的事情,都是实实在在的做跟工作相关对公司有益的事情。相信在伍经理的带领下现在是这样,以后同样也是这样。

      拼搏:公司给的每一个任务不管它多难,如果工作没有完成我们会晚上加班,也要尽可能的完成当天的工作。如果工作实在忙,为了赶进度我们放弃周末休息时间也要尽可能的使项目提前。

      创新:现在我们开始项目的时候都会进行研讨,一般都会进行一个效率和逻辑的分析与讨论,保证程序正确的前提尽可能的提高程序的效率。

      互助:我们小组内只要任何一个人出现技术或其它的问题,我们都会彼此都会尽可能的去帮助他。不会因为某一个人而拖住整个项目滞后。

      交流:我们在项目中会及时沟通自己的收获,特别是一些针对性的技术问题。这样可以省了很多重复研究的时间,这是一笔很可观的时间。

      在交流中只要我会的,我懂的,我不会去吝啬。我会积极的去与你交流,我的团队名言“人强团则强,人弱团则削”。

       三、个人成长

      通过公司这快一年的锻炼与学习我真的进步了很多,不管从技术上还是做事上,都不像以前那样了。我在公司学到的懂得的使我飞速成长。

      技术上:不管从语言上还是做事的逻辑上都得到了很大的的提高。现在在软件小组里面自己能独立完成一部分工作,承担自己的责任。

    程序员工作总结

      程序员是从事程序开发、程序维护的专业人员。以下是我整理的程序员工作总结,希望对大家有帮助!

      程序员工作总结1

      光阴如梭,一年的工作转瞬即将成为历史,伴随着新年钟声的临近,我们依依惜别硕果累累的20xx年,满怀热情的迎来即将到来的20xx年。在这年终之际,现对我来公司这几个月的时间里,总结自己所做的工作,分析在工作中的得与失,现汇报如下:

      20xx年的六月份,我带着好奇而欢快的心情来到我心目中向往的神圣之地北京。这是我毕业后第一个目标,来北京发展。我离开了我上学的原始领域,和我的同学们踏入北京之地。说句好听的,我的技术生涯还是很幸运的,当然这是我相对于留守本地找工作的同学来说的,面对高昂的学费和残酷的社会现实,选择本专业就业还是有一定困难的,在北京中关村混了几个月后,幸运地找到了我人生的第一份工作,做Java程序的工作。也就是来到咱们公司—北京联合兴辰。

      来到贵公司,学了半个皮毛的MVC和SSH的我有了份工作,我感到十分的庆幸,也承担了第一个项目,能一个人自主开发的项目。在这里,终于能够将学到的那点东西派上用场。从技术的角度来讲,20xx年我的关键词就是SSH,其次就是Hibernate。

      这几个月淡淡无奇,学到的东西很多,有框架上的、Mysql数据库的,等等,但是也都是在皮毛上的,掌握着能熟练使用而已。首先,做程序员的要记住第一条经验:“学历代表过去、能力代表现在、学习代表未来。”我个人觉得学历并不代表全部,我们每天都可以学到新的知识,知识是可以一点点积累的,只要肯努力,一切皆有可能.其次,一定要确定自己的发展方向,并为此目的制定可行的计划。不要说什么,“我刚毕业,还不知道将来可能做什么?”“跟着感觉走,先做做看”。因为,这样的观点会通过你的潜意识去暗示你的行为无所事事、碌碌无为。一直做技术,将来成为专家级人物?向管理方向走,成为职业经理人?先熟悉行业和领域,将来自立门户?还是先在行业里面混混,过几年转行做点别的?这很重要,这是你值得深思的问题,它将决定你近几年、十年内“做什么事情才是在做正确的事情!。”

      软件开发团队中,技术不是万能的,但没有技术是万万不能的!在技术型团队中,技术与人品同等重要,当然长相也比较重要么。在软件项目团队中,技术水平是受人重视和尊重的重要砝码。无论你是做ERP、管理、系统分析、设计、编码,还是产品管理、测试、文档、实施、维护,多少你都要有技术基础。但是你没有这方面的基础是万万不能胜任你的工作的详细制定自己软件开发专业知识学习计划,并注意及时修正和调整(软件开发技术变化实在太快)。请牢记:“如果一个软件开发人员在1、2年内都没有更新过自己的知识,那么,其实他已经不再属于这个行业了。”

      不要告诉自己没有时间。时间就像海绵里的水,多学一些技能对于我们来说亏不到自己,我们的工作从学而来,就是靠着每天的学习,交流,做人中得到书籍是人类进步的阶梯,对软件开发人员尤其如此。我的项目经理经常说,趁着自己还年轻,花几个钱买书看看,书籍是学习知识的ZUI有效途径,不要过多地指望在工作中能遇到“世外高人”,并不厌其烦地教你。只有通过自学将书本变成的自己智慧,才算是真正拥有了它。不要仅局限于对某项技术的表面使用上,哪怕你只是偶尔用一、二次。

      对于一个做程序的,试试学习其领域的相关知识点,对各个平台都要了解,向什么JavaEE,J2ME,JavaSE,VB,VCC#,C++这些程序啊,也要试着去了解他们,虽然程序的套路基本是差不多的,但是也各有千秋的,我是学Java的,当然Java很强大,我就很爱Google出的那个安卓系统,Java实在太牛啦!不得不惊叹,例如我没有事的时候也因该提醒自己学习一些JBoss、Spring、Hibernate等等优秀的开源产品或者框架,抽空看看大师们是如何抽象、分析、设计和实现那些类似问题的通用解决方案的。试着研究一下jar包,知道每个jar的功能和实现的方法,免得自己以后的工作遇到一些让你不明就里、一头雾水的问题,因为,很多东西你“知其然且知其所以然”!在一种语言上编程,但别为其束缚了思想。“代码大全”中说:“深入一门语言编程,不要浮于表面”。深入一门语言开发还远远不足,任何编程语言的存在都有其自身的理由。

      有时候咱们会遇到一些问题,你单纯的用着一种方法有时候会解决不了问题,或者遇到问题卡在那里啦,这是你需要的是灵感。灵感来自那里,你可以借鉴Spring、Hibernate、JBoss等等优秀的开源框架的设计思想,你可以参照Java的IoC、AOP的设计思路,你可以从其他语言的程序中借鉴他们的套路,这就是我们的灵感,俗话说“他山之石、可以攻玉”。养成总结与反思的习惯,并有意识地提炼日常工作成果,形成自己的个人源码库、解决某类问题的通用系统体系结构、甚至进化为框架。我们在做程序的时候,别人为什么要提示你把每个方法都要写上注释,注释这段代码是干什么的,这是做好一个程序员基本的要诀,这就是你的基本功,当然在写代码的时候也不是都是有用的代码,有些功能是可以通用的,咱们为什么不可以给他打包封装jar,将来或者以后会用到呢,为什么会有那么多很牛的框架,这些都是程序员们提炼出来的,形成一整套的代码结构和体系,被人用的时候感觉非常好用,我们目前写不了这么牛的程序,但是还是可以形成自己的个人源码库的。

      心态有多开放,视野就有多开阔。不要抱着自己的技术和成果,等到它们都已经过时变成垃圾了,才拿出来丢人现眼。请及时发布自己的研究成果。例如你在网上看到别人遇到问题,这个问题可能你之前也遇到啦,不要抱着你那自私的心态,背后说“累死你,自己去找吧,小样“,建议大家,上你的CSDN号,我感觉这个东东很不错,技术交流。咱们“与人交换苹果之后,每个人还是只有一个苹果;但交换思想之后,每个人都拥有两种思想”,道理大家都懂,但有多少人真正能做到呢?我的反思不要去做技术上的高手,学会做人。提高自己的专业技能,能胜任工作。

      提高软件知识和技术只是问题的表面,本质是要提高自己认识问题、分析问题、解决问题的思想高度。在能胜任工作的基础上,立即去涉猎其它领域的专业知识,丰富自己的知识体系、提高自己的综合素质,尤其是那些目标不在技术方面的朋友。这也是本人的目标,再接再厉吧!

      程序员工作总结2

      时间一晃而过,转眼间到公司已经半年多了。这是我人生中弥足珍贵的一段经历。在这段时间里各级领导在工作上给予了我极大的帮助,在生活上给予了我极大的关心,让我充分感受到了领导们“海纳百川”的`胸襟,感受到了大发人“不经历风雨,怎能见彩虹”的豪气。在对公司各级领导肃然起敬的同时,也为我有机会成为公司的一份子而自豪。在这半年多的时间里,在领导和同事们的悉心关怀和指导下,通过自身的努力,各方面均取得了一定的进步,现将我的工作情况作如下汇报。

      一、通过培训学习和日常工作积累使我对公司有了一定的新的认识。在5月中旬我来到了公司信息科技有限公司参加招聘,经过几轮面试和笔试,终于能够有幸加入了公司,在我进入公司时我拿到的第一份资料就是公司介绍和新员工入职说明,当时只是觉得公司很正规,很强大。在和部门领导以及项目经理交流后,感觉公司很亲切,很温馨。对其它方面就不太知道了,特别是对视频监控几乎一无所知。通过三个月的亲身体会,对智能交通和公司有了一定了解。

      公司的理念在平时的工作以及项目开发时体现的淋漓尽致,本人对公司的理念非常认同。公司发展不忘回报社会的壮举,令人敬佩。公司以人为本、尊重人才的思想在实际工作中贯彻,这是公司能发展壮大的重要原因。在十年左右的时间实现跨越发展的确很不容易,在智能交通行业深入发展是公司的雄心壮志,也是凝聚人才的核心动力。现在公司在视频监控以及安防行业起到了举足轻重的地位,今后还将更加辉煌。

      二、遵守各项规章制度,认真工作,使自己素养不断得到提高。爱岗敬业的职业道德素质是每一项工作顺利开展并最终取得成功的保障。在这半年多的时间里,我能遵守公司的各项规章制度,兢兢业业做好本职业工作,半年来从未迟到早退,用满腔热情积极、认真地完成好每一项任务,认真履行岗位职责,平时生活中团结同事、不断提升自己的团队合作精神。一本《细节决定成败》让我豪情万丈,一种积极豁达的心态、一种良好的习惯、一份计划并按时完成竟是如此重要,并最终决定一个的人成败。这本书让我对自己的人生有了进一步的认识,渴望有所突破的我,将会在以后的工作和生活中时时提醒自己,以便自己以后的人生道路越走越精彩。

      三、认真学习岗位职能,工作能力得到了一定的提高。根据目前工作分工,我的主要工作任务是:

      (1)参与公司软件项目的开发与测试;

      (2)负责安徽省路警联合指挥中心软件系统的维护工作。通过完成上述工作,使我认识到一个称职的开发人员应当具有良好的语言表达能力、扎实的技术能力、较强的逻辑处理能力、灵活的应变问题能力、有效的对外联系能力。在参与项目开发的过程中,发现很多看似简单的工作,其实里面还有很多技巧。

      四、不足和需改进方面。

      虽然加入公司这个大家庭已经半年有余,对开发技术掌握的还不是很深,对发现问题的处理还不是很全面,对分工的工作还没有形成系统的计划。随着对公司和工作的进一步熟悉,我也希望能够在今后的工作中更加迅速的提升自己的业务能力以及技术能力,我觉得多做一些工作更能体现自己的人生价值。“业精于勤而荒于嬉”,在以后的工作中我要不断学习业务知识,通过多看、多问、多学、多练来不断的提高自己的各项业务技能。学无止境,时代的发展瞬息万变,各种学科知识日新月异。我将坚持不懈地努力学习各种知识,并用于指导实践。在今后工作中,要努力做好开发人员的本职工作,把自己的工作创造性做好做扎实,为项目的开发以及公司的发展贡献自己的力量。

      程序员工作总结3

      我是一名程序员,在过去的一年里,软件研发部团结协作,以及在公司这充满奋斗的环境下,我以严肃认真的工作态度和百折不饶的精神,努力的完成了公司的各项工作,在软件研发、团队协作和个人成长上也取得了一定的成绩。在公司一年的工作已经结束,特向公司总结汇报如下:

       一、软件研发

      根据公司的安排,项目的需要。在自身的努力、伍经理的帮组,团队的合作下,克服重重技术困难,增长了工作经验,收获丰盈:

      1、asp开发

      以前我在其他公司也做过一些开发,但是底层和架构与页面样式我都是没有涉及到的。通过这一年在本公司的的这些项目程序中的锻炼,我成长了,我学会了很多很多。

      首先,面向对象语言的收获。对于当前编程的主流思想是对象,任何事物都可以用对象来表示。以前理解这些话很费解都是从表面上理解,没有从中的体会,通过这次asp项目的开发,不管是数据还是外部一些条件我们都可以抽象成对象,都可以用对象来表示,具体可以用语言中的类方等。asp如此,c#如此java也同样如此。

      其次,具备独立完成vb知识方面的能力。以前没有做过vb的东西,加上这次asp的做,这次涉及到的领域也非常广,常用的重要的都有涉及,并且还补充xml,java实际操作中空白的部分。通过这一年的开发,我能胜任这方面的工作,能独立完成这方面的工作。

      再次,c#方面存在一些不足。LocALhOST通过c#这次软件的开发,也发现自己的不足,如基础知识掌握不牢,缺乏编程整体思想。这些都是需要在工作中完善和改进的。

      2、数据库开发

      数据库是伴随着项目以来用的最多最平凡的技术。以前对数据库只是会一些简单常用的操作,经过这一年项目的实战,对数据库的操作增加了一些丰富的经验。为以后的工作和经验的积累都奠定了坚实的基础。同时在项目中还用到了oracel与access数据库,这是我的收获。

      优点:

      能熟练的运用数据库技术进行开发。特别是对sql数据库的操作,经过这么长时间的积累,基本上能合理的设计和新建数据库,同时在数据结构上也加强了对数据库的理解。通过项目的实践现在能熟练使用和编写多种sql语句。还掌握了一些关于数据库优化sql语句优化的方法,能进行一些简单的优化。

      缺点:

      数据是一门比较先进的技术,并不是你会写一些sql语句,能建几个数据库你就是数据库工程师。要成为一个好的数据库管理员是要经过长时间的工作积累。针对自己的不足,在以后的工作和学习中多接触,多运用新的知识点。充实自己的经验和知识储备。

       二、团队协作

      上面的成功与收获,除了自身努力外,以及公司的支持。是这个团队铸造了我。我们这个团队也是因为有了我们这些拼搏协作的队员,使得它成为一个具有务实、拼搏、创新精神的团队。我与软件研发小组是一个整体,这里的团队总结也就是我在这个团队中的收获。

      务实:公司下发的任务,下发的工作,件件都是用心去做的。我们这个团队中没有一个人在工作的时候做了工作以外的事情,都是实实在在的做跟工作相关对公司有益的事情。相信在伍经理的带领下现在是这样,以后同样也是这样。

      拼搏:公司给的每一个任务不管它多难,如果工作没有完成我们会晚上加班,也要尽可能的完成当天的工作。如果工作实在忙,为了赶进度我们放弃周末休息时间也要尽可能的使项目提前。

      创新:现在我们开始项目的时候都会进行研讨,一般都会进行一个效率和逻辑的分析与讨论,保证程序正确的前提尽可能的提高程序的效率。

      互助:我们小组内只要任何一个人出现技术或其它的问题,我们都会彼此都会尽可能的去帮助他。不会因为某一个人而拖住整个项目滞后。

      交流:我们在项目中会及时沟通自己的收获,特别是一些针对性的技术问题。这样可以省了很多重复研究的时间,这是一笔很可观的时间。

      在交流中只要我会的,我懂的,我不会去吝啬。我会积极的去与你交流,我的团队名言“人强团则强,人弱团则削”。

       三、个人成长

      通过公司这快一年的锻炼与学习我真的进步了很多,不管从技术上还是做事上,都不像以前那样了。我在公司学到的懂得的使我飞速成长。

      技术上:不管从语言上还是做事的逻辑上都得到了很大的的提高。现在在软件小组里面自己能独立完成一部分工作,承担自己的责任。

    如何学好java语言啊?

    建议一:有系统的学习方案,系统的学习教程,先把Java学了一遍之后才是真正的入门,然后就是不断的练习,不断的巩固,为之后的工作打下坚实的基础。

    建议二:学习Java不要先看书学,一定要先把一块的知识点学完一遍,并且自己多多少少会动手操作,然后去看书温习。还有不要盲目的看视频,很多人都是光看视频,然后在心里没有一个操作的概念,这样的学习方法最后一定会浪费时间到放弃,所以学习Java之前一定要知道这些东西,这都是走过来的人以前走的弯路。

    建议三:很多人都会有一个疑问,就是学习Java能看懂,但是不会写,所以学习Java一定要掌握一个有效率的学习方法,一个适合自己的学习方法,作为一个新人,千万不要自己瞎摸索,没有必要,可以请教别人一定要去问。

    建议四:一定要有一个明白人去指导你,Java的专业程度很强,80%的问题自己很难解决,而且会很浪费时间,一个小问题可以困扰一天,这样自信心会受到严重的打击,如果没有人指导,可以加我

    学习Java的四个阶段:

    一:Javase基础

    二:网页三剑客html+css+js

    三:JavaWeb和数据库:

    四:JavaEE框架:企业级开发,Struts2、Spring框架、Hibernate框架、Maven核心技术、MyBaits框架、高手进阶;

    如果找不到学习资源,可以点击这里下载。

    当你学完了Java,应该如何去找工作?

    一.最重要的还是自身技能,这是硬件标准,标配,自己能力怎么样自己心里最清楚,如果自己都觉得自己不会的,我觉得还是好好提升技术吧。

    二.简历,写简历需要有一定的学问,一篇要把你所有的优势说明白,而且现在写简历,千万不可以写的太死板,一定要写的另类一些,因为简历太多,比如你写,喜欢学习,性格随和,等等太普遍,你会写别人也会写,没有新意,而且在写项目经历的时候更要注意。

    三.面试技巧,面试是最重要的一部分,你是否能应聘成功取决你面试怎么样,面试官都是一些经验老道的,所以你回答他问题的时候要注意技巧,比如:当他问道你一个异常的时候的,你不会,但是你不要说不会,你可以说之前我遇到过,但是现在忘了,如果我遇到可以解决等等。当然了,如果你自己很NB,会很多东西,信心十足,你自然会面试成功,所有的一切取决于你的本领如何。

    希望可以帮助到大家,对于学习Java行业任何问题,可以随时私信我,希望大家学有所成,早日高薪

    SQL实战新手入门:前言

       前言

      信息泛滥并没有减弱的趋势 人们被来自电视 Internet和塞满邮箱的广告等各种各样的信息所淹没 令人遗憾的是 随着信息数量的增长 信息的质量却在急剧下降 图书被期刊和杂志取代 然后被报纸 Web页面 博客取代 最终又被(eet)取代 信息量变得越来越庞大 也变得越来越不可信赖 更糟糕的是 在Internet时代数据永远不会真正消失 它不停地累积 隐藏在各种文件 日志和数据库中 根据Google的前CEO Eric Schmidt的说法 现在人类在两天之内创造的数据量就相当于自从出现书写记录到 年(或者任何一年)所创造的数据 即现在只需要两天就会创造出大约 EB(即 亿GB)的数据 这一步伐还在不停地加速

      当以电子化方式存储数据变成现实之后 它也带来了自己的规则 要理解数据的含义 人们必须去学习相应的语言 关系数据库理论为人们带来了对电子化数据的掌控能力 它采用结构化查询语言(Structured Query Language SQL)来处理数据 到目前为止 关系数据库获取了巨大的成功

      自从 世纪 年代第一次提出关系数据库以来 关系数据库和SQL已经取得了长足的进步 关系数据库和SQL中包含的那些概念对于初学者来说可能并不直观 本书将为读者抽丝剥茧 使读者理解SQL背后的原理 既让读者了解SQL的强大功能 也了解它存在的局限

       读者对象

      本书从入门知识开始介绍 读者无须具备SQL或关系数据库的预备知识 本书将带领读者走入SQL的发现之旅 读者将亲自创建示例数据库 它不仅结合了本书中所介绍的SQL概念 还将通过几次反复重构引入数据建模 查询调整和优化的概念 本书还介绍了一些适用于每一种SQL的最佳实践

      本书适合于准备学习关系数据库程序设计的计算机程序员 也适合那些希望从数据库中释放更强大威力的商业用户 SQL是关系数据库世界的通用语言 每一个对学习SQL这门强大语言感兴趣的人都适合阅读本书

      先前已具有一定数据库使用经验的读者可以略过前两章 直接跳到更高级的内容 当然也可以复习一下这两章中介绍的重要原则

       内容提要

      本书介绍了当前已发布的SQL标准SQL: 把最主要的精力放在了SQL语言实际的运用上 强调了不同SQL实现之间存在的差异 本书介绍了很多示例 在这些示例中使用了最新版本的现代数据库系统对SQL的具体实现 这些数据库要么是可以免费下载的Express版本 要么是免费的开源软件 另外 本书还介绍了目前最流行的桌面型数据库软件Microsoft Access和OpenOffice 本书中介绍的数据库包括

      IBM UDB

      Oracle g

      Microsoft SQL Server / /

      MySQL /

      PostgreSQL

      Microsoft Access /

      带有嵌入式 HSQLDB的OpenOffice BASE

       本书结构

      本书从整体着眼 向读者介绍了关系数据库的一般概念 特别是SQL中的概念 通过一个反复重构数据库的过程 循序渐进地向读者介绍了数据库的各种知识 在这一过程中 对于开始时介绍的每一个概念 随后都进行了更详细的分析 从而启发读者理解这些概念背后的关联性

      第 章简要地介绍了SQL及其背后的关系理论 这一章只是浮光掠影般地介绍了数据库最基本的概念 后面的各章都在此基础上展开 该章介绍了数据与信息的区别 一些基本的原理还需要在后面章节中进一步解释 这一章还对本书中所使用的关系数据库管理系统(RDBMS)进行了一个概述

      第 章对这些概念进行了更深入的介绍 根据关系模型的分析 应该将无组织的数据结构化 使之符合关系模型的要求 即将 冰箱磁铁 模式转换为 斗柜 模式 然后再将其转换为关系数据库中实际的表

      第 章进一步介绍了关系模型 初步介绍了数据库的基本设计和规范化的基本过程 这一章还介绍了一些对规范化数据执行查询的SQL工具 此外 该章还介绍了动态SQL

      SQL是一种基于集合的语言 这使得它既有强大的功能 也存在一定的局限 第 章讨论了最流行的过程化扩展(例如Oracle的PL/SQL和Microsoft的Transact SQL) 这一章还介绍了SQL函数 SQL函数可以作为一种补充手段 以弥补在处理基于记录的逻辑时SQL存在的固有不足

      第 章介绍了聚合数据 总结了这种方式的威力和局限 该章将前面章节中介绍过的SQL聚合函数提高到了一个新的层次 演示了如何使用SQL来获取数据的聚合值

      第 章介绍了子查询 当数据集是交错的 查询数据需要依靠多层次的数据筛选时 可以将一个查询作为另一个查询的筛选条件 可以调整SQL语句 用JOIN代替子查询 这是贯穿本书的主题之一

      SQL的强大功能在于处理存储在多个关系表中的数据 第 章介绍了SQL如何在单个数据集中联合这些关系表的数据

      本书介绍的是基本的SQL概念 打开了进一步学习SQL的大门 第 章是SQL发现之旅的下一站 它介绍了进一步学习SQL时应该考虑的问题

      第 章介绍了性能优化技术 描述了在优化查询和数据库环境时常用的方法和最佳实践 第 章讨论了多用户环境中关系数据库的工作原理 介绍了SQL中实现的处理并发数据访问的机制

      SQL所有的操作都与结构和顺序有关 毕竟它是结构化查询语言 真实的数据可以是各种规模和结构 第 章介绍了SQL如何处理半结构化数据(XML文档) 非结构化数据(文本文件)和二进制数据(例如图片和声音)

      第 章简要地讨论了数据库领域的最新发展 例如列式数据库 NoSQL数据库 对象数据库和面向服务的架构(SOA) 以及它们与SQL的关系

      对于本书所讨论的每一种数据库 附录A按部就班地描述了安装示例数据库Library的过程 以及如何使用特定的指令生成Library数据库的初始数据 可以从本书支持网站上下载到这些SQL脚本

      对于本书介绍的关系数据库软件包 附录B提供了一个详细的安装步骤

      附录C描述了每一种数据库所提供的工具 使用这些工具可以访问 创建数据库对象 操纵存储在表中的数据

      附录D介绍了开源项目SQuirreL Universal SQL Client 可以通过Java Database Connectivity(JDBC)接口 使用SQuirreL Universal SQL Client来访问各种数据库 该附录详细地介绍了如何安装和配置该软件

       学习本书的条件

      为了充分利用本书 建议下载和安装本书中使用的关系数据库软件 这些软件绝大多数都是免费的 或者具有免费的试用版 可以按照附录B中介绍的步骤来安装这些软件

       支持网站和代码

      在学习每一章时 建议下载相应的SQL脚本 创建并生成数据库 可以从 wrox 或者 agilitator 下载到本书的代码 在支持网站中 可以使用搜索框来查找指定名称的图书 在找到指定的图书之后 单击Download Code链接就可以访问允许下载的文件 可以通过HTTP或FTP下载这些代码 所有的文件都是以ZIP格式保存

      本书的ISBN是 通过ISBN号查找本书 要比通过图书名称来查找更加方便

      此外 还可以从Wrox的下载页面 wrox /dynamic/books/download aspx下载到本书的代码 只要单击Discovering SQL: A Hands On Guide for Beginners链接 就可以访问允许下载的文件

       勘误表

      尽管我们已经尽了最大的努力来保证文章或代码中不出现错误 但是错误总是难免的 如果您在本书中找到了错误 例如拼写错误或代码错误 请告诉我们 我们将非常感激 通过勘误表 可以让其他读者避免走入误区 当然 这还有助于提供更高质量的信息

      要在网站上找到本书英文版的勘误表 可以登录// wrox 通过Search工具或书名列表查找本书 然后在本书的细目页面上 单击Book Errata链接 在这个页面上可以查看到Wrox编辑已提交和粘贴的所有勘误项 完整的图书列表还包括每本书的勘误表 网址是 wrox /misc pages/booklist s

      如果你在勘误表上没有找到错误 那么可以到 wrox /contact/techsupport s上完成上面的表格 并把找到的错误发送给我们 我们将会核查这些信息 如果无误的话 会把它放置到本书的勘误表中 并在本书的后续版本中更正这些问题

       p p wrox

      要与作者和同行讨论 请加入p p wrox 上的P P论坛 这个论坛是一个基于Web的系统 便于您张贴与Wrox图书相关的消息和相关技术 与其他读者和技术用户交流心得 该论坛提供了订阅功能 当论坛上有新的消息时 它可以给您传送感兴趣的论题 Wrox作者 编辑和其他业界专家和读者都会到这个论坛上来探讨问题

      在//p p wrox 上 有许多不同的论坛 它们不仅有助于阅读本书 还有助于开发自己的应用程序 要加入论坛 可以遵循下面的步骤

      ( ) 进入p p wrox 单击Register链接

      ( ) 阅读使用协议 并单击Agree按钮

      ( ) 填写加入该论坛所需要的信息和自己希望提供的其他信息 并单击Submit按钮

      ( ) 你会收到一封电子邮件 其中的信息描述了如何验证账户和完成加入过程

      不加入P P也可以阅读论坛上的消息 但要张贴自己的消息 就必须加入该论坛

      加入论坛后 就可以张贴新消息 回复其他用户张贴的消息 可以随时在Web上阅读消息 如果要让该网站给自己发送特定论坛中的消息 可以单击论坛列表中该论坛名旁边的Subscribe to this Forum图标

      关于使用Wrox P P的更多信息 可阅读P P FAQ 了解论坛软件的工作情况以及P P和Wrox图书的许多常见问题 要阅读FAQ 可以在任意P P页面上单击FAQ链接

           返回目录 SQL实战新手入门

           编辑推荐

           Oracle索引技术

           高性能MySQL

    lishixin/Article/program/SQL/201311/16496

    Copyright © 2019- net188.cn 版权所有

    违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

    本站由北京市万商天勤律师事务所王兴未律师提供法律服务