主键(primary key)

能够唯一标识表中某一行的属性或属性组。
一个表只能有一个主键,但可以有多个候选索引。
主键常常与外键构成参照完整性约束,防止出现数据不一致。
主键可以保证记录的唯一和主键域非空,数据库管理系统对于主键自动生成唯一索引,
所以主键也是一个特殊的索引。

外键(foreign key)

是用于建立和加强两个表数据之间的链接的一列或多列。
外键约束主要用来维护两个表之间数据的一致性。
简言之,表的外键就是另一表的主键,外键将两表联系起来。
一般情况下,要删除一张表中的主键必须首先要确保其它表中的没有相同外键
(即该表中的主键没有一个外键和它相关联)。

索引(index)

是用来快速地寻找那些具有特定值的记录。
主要是为了检索的方便,是为了加快访问速度, 按一定的规则创建的,一般起到排序作用。
所谓唯一性索引,这种索引和前面的“普通索引”基本相同。
但有一个区别:索引列的所有值都只能出现一次,即必须唯一。

总结:

主键一定是唯一性索引,唯一性索引并不一定就是主键。

 一个表中可以有多个唯一性索引,但只能有一个主键。

主键列不允许空值,而唯一性索引列允许空值。

主键可以被其他字段作外键引用,而索引不能作为外键引用。

首先,我们看一个图:
1533548230146872.jpg

影响MySQL-A数据库的操作,在数据库执行后,都会写入本地的日志系统A中。

假设,实时的将变化了的日志系统中的数据库事件操作,在MYSQL-A的3306端口,通过网络发给MYSQL-B。

MYSQL-B收到后,写入本地日志系统B,然后一条条的将数据库事件在数据库中完成。

那么,MYSQL-A的变化,MYSQL-B也会变化,这样就是所谓的MYSQL的复制,即MYSQL replication。

在上面的模型中,MYSQL-A就是主服务器,即master,MYSQL-B就是从服务器,即slave。

日志系统A,其实它是MYSQL的日志类型中的二进制日志,也就是专门用来保存修改数据库表的所有动作,即bin log。【注意MYSQL会在执行语句之后,释放锁之前,写入二进制日志,确保事务安全】

日志系统B,并不是二进制日志,由于它是从MYSQL-A的二进制日志复制过来的,并不是自己的数据库变化产生的,有点接力的感觉,称为中继日志,即relay log。

可以发现,通过上面的机制,可以保证MYSQL-A和MYSQL-B的数据库数据一致,但是时间上肯定有延迟,即MYSQL-B的数据是滞后的。

【即便不考虑什么网络的因素,MYSQL-A的数据库操作是可以并发的执行的,但是MYSQL-B只能从relay log中读一条,执行下。因此MYSQL-A的写操作很频繁,MYSQL-B很可能跟不上。】

2.主从复制的几种方式

同步复制

  所谓的同步复制,意思是master的变化,必须等待slave-1,slave-2,...,slave-n完成后才能返回。
  这样,显然不可取,也不是MYSQL复制的默认设置。
  比如,在WEB前端页面上,用户增加了条记录,需要等待很长时间。

异步复制

如同AJAX请求一样。master只需要完成自己的数据库操作即可。
至于slaves是否收到二进制日志,是否完成操作,不用关心。MYSQL的默认设置。

半同步复制

master只保证slaves中的一个操作成功,就返回,其他slave不管。
这个功能,是由google为MYSQL引入的。

3.主从复制分析

问题1:master的写操作,slaves被动的进行一样的操作,保持数据一致性,那么slave是否可以主动的进行写操作?

假设slave可以主动的进行写操作,slave又无法通知master,这样就导致了master和slave数据不一致了。                    
因此slave不应该进行写操作,至少是slave上涉及到复制的数据库不可以写。
实际上,这里已经揭示了读写分离的概念。

问题2:主从复制中,可以有N个slave,可是这些slave又不能进行写操作,要他们干嘛?

可以实现数据备份。
类似于高可用的功能,一旦master挂了,可以让slave顶上去,同时slave提升为master。
异地容灾,比如master在北京,地震挂了,那么在上海的slave还可以继续。
主要用于实现scale out,分担负载,可以将读的任务分散到slaves上。
很可能的情况是,一个系统的读操作远远多于写操作,因此写操作发向master,读操作发向slaves进行操作

问题3:主从复制中有master,slave1,slave2,...等等这么多MYSQL数据库,那比如一个JAVA WEB应用到底应该连接哪个数据库?

当 然,我们在应用程序中可以这样,insert/delete/update这些更新数据库的操作,
用connection(for master)进行操作,select用connection(for slaves)进行操作。
那我们的应用程序还要完成怎么从slaves选择一个来执行select,例如简单的轮循算法。
这样的话,相当于应用程序完成了SQL语句的路由,而且与MYSQL的主从复制架构非常关联,
一旦master挂了,某些slave挂了,那么应用程序就要修改了。
能不能让应用程序与MYSQL的主从复制架构没有什么太多关系呢?可以看下面的图:

1533548233143658.jpg

找一个组件,application program只需要与它打交道,用它来完成MYSQL的代理,实现SQL语句的路由。
mysql proxy并不负责,怎么从众多的slaves挑一个?可以交给另一个组件(比如haproxy)来完成。
这就是所谓的MYSQL READ WRITE SPLITE,MYSQL的读写分离。

问题4:如果mysql proxy , direct , master他们中的某些挂了怎么办?

总统一般都会弄个副总统,以防不测。同样的,可以给这些关键的节点来个备份。

问题5:当master的二进制日志每产生一个事件,都需要发往slave,如果我们有N个slave,那是发N次,还是只发一次?

如果只发一次,发给了slave-1,那slave-2,slave-3,...它们怎么办?
显 然,应该发N次。实际上,在MYSQL master内部,维护N个线程。
每一个线程负责将二进制日志文件发往对应的slave。master既要负责写操作,还的维护N个线程。
负担会很重。可 以这样,slave-1是master的从,slave-1又是slave-2,slave-3,...的主,
同时slave-1不再负责select。 slave-1将master的复制线程的负担,转移到自己的身上。
这就是所谓的多级复制的概念。

问题6:当一个select发往mysql proxy,可能这次由slave-2响应,下次由slave-3响应,这样的话,就无法利用查询缓存了。

应该找一个共享式的缓存,比如memcache来解决。将slave-2,slave-3,...
这些查询的结果都缓存至mamcache中。

问题7:随着应用的日益增长,读操作很多,我们可以扩展slave,但是如果master满足不了写操作了,怎么办呢?

scale on ?更好的服务器? 没有最好的,只有更好的,太贵了。。。
scale out ? 主从复制架构已经满足不了。
可以分库【垂直拆分】,分表【水平拆分】。

转载自: MySQL 主从复制与读写分离概念及架构分析

服务器环境:

master : linux/192.168.85.130,    mysql5.7
slave:linux/192.168.85.95        mysql5.7
均为空数据下
两台均为本地虚拟机,且均为lnmp搭建。

master:

修改master mysql配置文件

在[mysqld]中修改
vim /etc/my.cnf
log-bin=mysql-bin   #开启二进制文件
server-id=1    #唯一的  在msater和多台slave中确保唯一性
/etc/init.d/mysql reload  #重启mysql
 mysql -uroot -p  #登陆mysql

创建用户slave和master中通信的账户

mysql->CREATE USER 'devdb'@'%' IDENTIFED BY 'root'; #创建 devdb 用户, %全部IP, 密码为root;
mysql->GRANT REPLICATION SLAVE ON *.* 'devdb'@'%'; #分配mysql权限
mysql->flush privileges; #刷新权限
mysql->show master status; #查看master状态和二进制文件位置

请输入图片描述

slave:

修改slave mysql配置文件

vim /etc/my.cnf    #在[mysqld]中修改
log-bin=mysql-bin   #开启二进制文件 如果多台slave 可以对 一台slave进行,从而减少master的压力.
server-id=1    #唯一的  在msater和多台slave中确保唯一性    
/etc/init.d/mysql reload  #重启mysql
mysql -u root -p #登陆mysql

在slave登陆master

mysql> CHANGE MASTER TO 
    -> MASTER_HOST='192.168.85.130', #根据自己masterIP地址改
    -> MASTER_USER='devdb',
    -> MASTER_PASSWORD='slavepass',
    -> MASTER_LOG_FILE='mysql-bin.000025', # mstaer二进制文件
    -> MASTER_LOG_POS=12787;    
mysql->start slave; #启动同步进程
mysql->show slave status\G; #查看同步进程

请输入图片描述

若看都Slave_IO_Running和Slave_SQL_Running均为Yes; 表示同步成功。

以下为测试

master中创建test库 1536045847605551.png

slave中自动创建了test库
请输入图片描述

眼下,人工智能已经成为越来越火的一个方向。普通程序员,如何转向人工智能方向,是知乎上的一个问题。本文是对此问题的一个回答的归档版。相比原回答有所内容增加。

  一. 目的

  本文的目的是给出一个简单的,平滑的,易于实现的学习方法,帮助 “普通” 程序员踏入AI领域这个门。这里,我对普通程序员的定义是:拥有大学本科知识;平时工作较忙;自己能获取的数据有限。因此,本文更像是一篇 “from the scratch” 的AI入门教程。

  二. AI领域简介

  AI,也就是人工智能,并不仅仅包括机器学习。曾经,符号与逻辑被认为是人工智能实现的关键,而如今则是基于统计的机器学习占据了主导地位。最近火热的深度学习正是机器学习中的一个子项。目前可以说,学习AI主要的是学习机器学习。

  但是,人工智能并不等同于机器学习,这点在进入这个领域时一定要认识清楚。关于AI领域的发展历史介绍推荐看周老师写的《机器学习简介》。下面一个问题是:AI的门好跨么?其实很不好跨。我们以机器学习为例。

  在学习过程中,你会面对大量复杂的公式,在实际项目中会面对数据的缺乏,以及艰辛的调参等。如果仅仅是因为觉得这个方向未来会“火”的话,那么这些困难会容易让人放弃。考虑到普通程序员的特点,而要学习如此困难的学科,是否就是没有门路的?答案是否定的。只要制定合适的学习方法即可。

  三. 学习方法

  学习方法的设定简单说就是回答以下几个问题:我要学的是什么?我怎样学习?我如何去学习?这三个问题概括说就是:学习目标,学习方针与学习计划。学习目标比较清楚,就是踏入AI领域这个门。这个目标不大,因此实现起来也较为容易。“过大的目标时就是为了你日后放弃它时找到了足够的理由”。

  学习方针可以总结为 “兴趣为先,践学结合”。简单说就是先培养兴趣,然后学习中把实践穿插进来,螺旋式提高。这种方式学习效果好,而且不容易让人放弃。有了学习方针以后,就可以制定学习计划,也称为学习路线。下面就是学习路线的介绍。

  四. 学习路线

  我推荐的学习路线是这样的,如下图:

  072126_Tscd_2896879.png

  图1 AI领域学习路线图

  这个学习路线是这样设计的:首先了解这个领域,建立起全面的视野,培养起充足的兴趣,然后开始学习机器学习的基础,这里选择一门由浅入深的课程来学习,课程最好有足够的实验能够进行实战。基础打下后,对机器学习已经有了充足的了解,可以用机器学习来解决一个实际的问题。

  这时还是可以把机器学习方法当作一个黑盒子来处理的。实战经验积累以后,可以考虑继续进行学习。这时候有两个选择,深度学习或者继续机器学习。深度学习是目前最火热的机器学习方向,其中一些方法已经跟传统的机器学习不太一样,因此可以单独学习。除了深度学习以外,机器学习还包括统计学习,集成学习等实用方法。

  如果条件足够,可以同时学习两者,一些规律对两者是共通的。学习完后,你已经具备了较强的知识储备,可以进入较难的实战。这时候有两个选择,工业界的可以选择看开源项目,以改代码为目的来读代码;学术界的可以看特定领域的论文,为解决问题而想发论文。

  无论哪者,都需要知识过硬,以及较强的编码能力,因此很能考察和锻炼水平。经过这个阶段以后,可以说是踏入AI领域的门了。“师傅领进门,修行在个人”。之后的路就要自己走了。

  下面是关于每个阶段的具体介绍:

  0.领域了解

  在学习任何一门知识之前,首先第一步就是了解这个知识是什么?它能做什么事?它的价值在什么地方?如果不理解这些的话,那么学习本身就是一个没有方向的舟,不知道驶向何处,也极易有沉船的风险。了解这些问题后,你才能培养出兴趣,兴趣是最好的引路人,学习的动力与持久力才能让你应付接下来的若干个阶段。关于机器学习是什么,能做什么,它与深度学习以及人工智能的关系,可以看我写的博客 从机器学习谈起:

  1.知识准备

  如果你离校过久,或者觉得基础不牢,最好事先做一下准备复习工作。“工欲善其事,必先利其器”。以下的准备工作不多,但足以应付后面阶段的学习。

  数学:复习以下基本知识。线性代数:矩阵乘法;高数:求导;概率论:条件与后验概率。其他的一些知识可以在后面的学习的过程中按需再补;

  英文:常备一个在线英文词典,例如爱词霸,能够不吃力的看一些英文的资料网页;

  FQ:可以随时随地上Google,这是一个很重要的工具。不是说百度查的不能看,而是很多情况下Google搜出来的资料比百度搜的几十页的资料还管用,尤其是在查英文关键字时。节省时间可是很重要的学习效率提升;

  2.机器学习

  机器学习的第一门课程首推Andrew Ng的机器学习。这门课程有以下特点:难度适中,同时有足够的实战例子,非常适合第一次学习的人。cs229 这门课程我这里不推荐,为什么,原因有以下:

  时间:cs229 的时间太早,一些知识已经跟不上当今的发展,目前最为火热的神经网络一笔带过。而Cousera上神经网络可是用了两个课时去讲的!而且非常详细;

  教学:Ng在cs229 时候的教学稍显青涩,可能是面对网络教学的原因。有很多问题其实他都没有讲清楚,而且下面的人的提问其实也很烦躁,你往往不关心那些人的问题。这点在Coursera上就明显得到了改善,你会发现Ng的教学水平大幅度改善了,他会对你循循善诱,推心置腹,由浅入深的教学,在碰到你不明白的单词术语时也会叫你不要担心,更重要的,推导与图表不要太完善,非常细致清晰,这点真是强力推荐;

  字幕:cs229 的字幕质量比Coursera上的差了一截。Coursera上中文字幕翻译经过了多人把关,质量很有保证;

  作业:cs229 没有作业,虽然你可以做一些,但不会有人看。这点远不如Coursera上每周有deadline的那种作业,而且每期作业提交上去都有打分。更重要的是,每期作业都有实际的例子,让你手把手练习,而且能看到自己的成果,成就感满满!

  3.实践做项目

  学习完了基础课程,你对机器学习就有了初步了解。现在使用它们是没有问题的,你可以把机器学习算法当作黑盒子,放进去数据,就会有结果。在实战中你更需要去关心如何获取数据,以及怎么调参等。如果有时间,自己动手做一个简单的实践项目是最好的。

  这里需要选择一个应用方向,是图像(计算机视觉),音频(语音识别),还是文本(自然语言处理)。这里推荐选择图像领域,这里面的开源项目较多,入门也较简单,可以使用OpenCV做开发,里面已经实现好了神经网络,SVM等机器学习算法。项目做好后,可以开源到到 Github 上面,然后不断完善它。实战项目做完后,你可以继续进一步深入学习,这时候有两个选择,深度学习和继续机器学习;

  4.深度学习

  深度学习:深度学习是目前最火热的研究方向。有以下特点:知识更新快,较为零碎,没有系统讲解的书。因此学习的资源也相对零散,下面是一些资源介绍。其中不推荐的部分并不代表不好,而是在这个初学阶段不合适:

  推荐,UFLDL: 非常好的DL基础教程,也是Andrew Ng写的。有很详尽的推导,有翻译,且翻译质量很高;推荐,Deep learning (paper):2015年Nature上的论文,由三位深度学习界的大牛所写,读完全篇论文,给人高屋建瓴,一览众山小的感觉,强烈推荐。如果只能读一篇论文了解深度学习,我推荐此篇。这篇论文有同名的中文翻译;推荐,Neural networks and deep learning:这本书的作者非常擅长以浅显的语言表达深刻的道理,虽然没有翻译,但是阅读并不困难;推荐,Recurrent Neural Networks: 结合一个实际案例告诉你RNN是什么,整篇教程学完以后,会让你对RNN如何产生作用的有很清晰的认识,而这个效果,甚至是读几篇相关论文所没有的;

  不推荐,Neural Networks for Machine Learning – University of Toronto | Coursera:深度学习创始人教的课,最大的问题是太难,而且老先生的吐字有时不是很标准;不推荐,Deep Learning (book):同样也是由深度学习大牛所写的书,但感觉就像是第二作者,也就是他的学生所写的。很多内容都讲了,但是感觉也没讲出什么内容来,只是告诉你来自那篇论文,这样的话可能直接阅读论文更合适。不推荐,cs231n:李菲菲的课程,很有名,专门讲CNN。但是这门课程有一个最大的问题,就是没有字幕,虽然有youtube的自动翻译字幕,但有还不如没有。

  5.继续机器学习

  深度学习未必就是未来的一定主流,至少一些大牛是这么认为的。传统的机器学习有如下特点,知识系统化,有相对经典的书。其中统计学习(代表SVM)与集成学习(代表adaboost)是在实践中使用非常多的技术。下面是相关资源:

  推荐,机器学习(周志华):如果是在以前,机器学习方面的经典教材首推PRML,但现在周老师的书出来以后,就不再是这样了。首先推荐读周老师的书。这本书有一个特点,那就是再难的道理也能用浅显精炼的语言表达出来。正如周老师的名言:“体现你水平的地方是把难的东西讲容易了,而不是把容易的东西讲难,想把一个东西讲难实在太简单”;

  不推荐,Pattern Recognition And Machine Learning:当前阶段不推荐。PRML是以贝叶斯的观点看待很多机器学习方法,这也是它的一大特色。但对于初学者来说,这种观点其实并无必要。而且此书没有中文翻译,当前阶段硬啃很容易放弃;

  6.开源项目

  当知识储备较为充足时,学习可以再次转入实践阶段。这时候的实践仍然可以分两步走,学习经典的开源项目或者发表高质量的论文。开源项目的学习应该以尽量以优化为目的,单纯为读代码而学习效果往往不太好。好的开源项目都可以在Github 里搜索。这里以深度学习为例。深度学习的开源优秀库有很多,例如torch,theano等等,这里列举其中的两个:

  推荐,DeepLearnToolbox:较早的一个深度学习库,用matlab语言撰写,较为适合从刚学习的课程转入学习。遗憾的是作者不再维护它了;

  推荐,tensorflow:Google的开源库,时至今日,已经有40000多个star,非常惊人,支持移动设备;

  7.会议论文

  较好的课程都会推荐你一些论文。一些著名的技术与方法往往诞生于一些重要的会议。因此,看往年的会议论文是深入学习的方法。在这时,一些论文中的内容会驱使你学习数学中你不擅长的部分。有时候你会觉得数学知识储备不够,因此往往需要学习一些辅助课程。

  当你看完足够的论文以后,在这个阶段,如果是在校学生,可以选择某个课题,以发论文为目的来学习研究。一般来说,论文是工作的产物。有时候一篇基于实验的论文往往需要你写代码或者基于开源项目。因此开源项目的学习与会议论文的工作两者之间是有相关的。

  两者可以同时进行学习。关于在哪里看论文,可以看一下CCF推荐排名,了解一下这个领域里有哪些优秀的会议。

  下面介绍两个图像与机器学习领域的著名顶级会议:

  CVPR:与另两个会议ICCV和ECCV合称计算机视觉领域的三大会,注意会议每年的主页是变动的,因此搜索需要加上年份;

  Conference on Neural Information Processing Systems:简称NIPS,许多重要的工作发表在这上面,例如关于CNN的一篇重要论文就是发表在上面;

  8.自由学习

  到这里了,可以说是进入这个门了。下面可以依据兴趣来自由学习。前阶段不推荐的学习资源也可随意学习,下面是点评:

  cs229:Ng写的讲义很不错,其中关于SVM的推导部分很清晰,想学习SVM推荐;

  Neural Networks for Machine Learning:大牛的视角跟人就是不一样,看看Hinton对神经网络是怎么看的,往往会让你有种原来如此的感悟。其实看这门课程也等同于读论文,因为几乎每节课的参考资料里都有论文要你读;

  CS231n: Convolutional Neural Networks for Visual Recognition:最新的知识,还有详细的作业。国内应该有团队对字幕进行了翻译,可以找找;

  PRML:作为一门经典的机器学习书籍,是很有阅读必要的,会让你对机器学习拥有一个其他的观察视角;

  五. 总结

  本文的目的是帮助对AI领域了解不深,但又想进入的同学踏入这个门。这里只说踏入,是因为这个领域的专精实在非常困难,需要数年的积累与努力。在进行领域学习前,充分认识自己的特点,制定合适的学习方法是十分重要的。

  首先得对这个领域进行充分了解,培养兴趣。在学习时,保持着循序渐进的学习方针,不要猛进的学习过难资源;结合着学习与实践相辅的策略,不要只读只看,实际动手才有成就感。学习某个资源时要有充分的目的,不是为了学开源项目而看代码,而是为了写开源项目而看;不是为了发论文而写论文,而是为了做事情而写论文。

  如果一个学习资源对你过难,并不代表一定是你的问题,可能是学习资源的演讲或撰写人的问题。能把难的问题讲简单的人才是真正有水平的人。所以,一定要学习优质资源,而不是不分青红皂白的学习。最后,牢记以兴趣来学习。学习的时间很长,过程也很艰难,而只有兴趣才是让你持之以恒,攻克难关的最佳助力。

  谨以此文与在学海中乘舟的诸位共勉。我就是一名普通程序员,刚刚转入AI领域,还有很多不足。希望此文可以帮助到大家。

  End.