事务相关
什么是事务?
事务:是由一组SQL语句组成的逻辑处理单元,事务具有以下4个属性,通常简称为事务。事务的ACID属性:
(1)原子性(Atomicity):
事务是一个原子操作单元,事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。(2)一致性(Consistent):
在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性;事务结束时,所有的内部数据结构(如B树索引或双向链表)也都必须是正确的。
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
例如转账,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。(3)隔离性(Isolation):
数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然。
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。(4)持久性(Durable):
事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。Mysql中会保存有相应的操作日志,即使遭遇故障依然能够通过日志恢复最后一次更新。
例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。简单理解:事务由一个或多个sql语句组成一个整体;
在事务中的操作,要么都执行修改,要么都不执行,
只有在该事务中所有的语句都执行成功才会将修改加入到数据库中,否则回滚到上一步。
Mysql实现事务
# start transaction; # 启动事务:
# update from account set money=money-100 where name='a';
# update from account set money=money+100 where name='b';
# commit; # 手动关闭事务'
MySQL的事务隔离级别
- 未提交读(Read Uncommitted):允许脏读,其他事务只要修改了数据,即使未提交,本事务也能看到修改后的数据值。也就是可能读取到其他会话中未提交事务修改的数据
- 提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)。
- 可重复读(Repeated Read):可重复读。无论其他事务是否修改并提交了数据,在这个事务中看到的数据值始终不受其他事务影响。
- 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
MySQL数据库(InnoDB引擎)默认使用可重复读( Repeatable read)
事务的并发问题
- 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
- 不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
- 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交(read-uncommitted) | 是 | 是 | 是 |
不可重复读(read-committed) | 否 | 是 | 是 |
可重复读(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
索引和约束
mysql 每个表最多16个约束
详细请参考:https://blog.csdn.net/fenglepeng/article/details/103141756
数据库五大约束
primary KEY:设置主键约束;
UNIQUE:设置唯一性约束,不能有重复值;
DEFAULT 默认值约束
NOT NULL:设置非空约束,该字段不能为空;
FOREIGN key :设置外键约束。
MySQL索引种类
- 普通索引:仅加速查询
- 唯一索引:加速查询 + 列值唯一(可以有null)
- 主键索引:加速查询 + 列值唯一 + 表中只有一个(不可以有null)
- 组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
- 全文索引:对文本的内容进行分词,进行搜索
# 其他
1、索引合并:利用多个单列索引查询
2、覆盖索引:在索引表中就能将想要的数据查询到
什么是索引合并?
# 索引合并访问方法可以在查询中对一个表使用多个索引,对它们同时扫描,并且合并结果。
# 此访问方法合并来自单个表的索引扫描; 它不会将扫描合并到多个表中。
什么是覆盖索引?
# 解释一:
就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。
# 解释二:
索引是高效找到行的一个方法,当能通过检索索引就可以读取想要的数据,那就不需要再到数据表中读取行了。
如果一个索引包含了(或覆盖了)满足查询语句中字段与条件的数据就叫做覆盖索引。
# 注意:MySQL只能使用B-Tree索引做覆盖索引
索引在什么情况下遵循最左前缀的规则?
主键和外键的区别?
'主键'
唯一标识一条记录
用来保证数据的完整性
主键只能有一个
'外键'
表的外键是另一个表的主键,外键可以有重复的,可以是空值
用来和其他表建立联系用的
一个表可以有多个外键
列举创建索引但是无法命中索引的8种情况。
使用'like ‘%xx’';select * from tb1 where name like '%cn';
使用'函数';select * from tb1 where reverse(name)='zgc';
使用'or';select * from tb1 where nid=1 or email='zgc@gmial.com';
特别的:当or条件中有未建立索引的列才失效,以下会走索引
# select * from tb1 where nid=1 or name='zgc';
# select * from tb1 where nid=1 or email='zgc@gmial.com' and name='zgc';
类型不一致,如果列是字符串类型,传入条件是必须用引号引起来,不然则可能会无法命中
select * from tb1 where name=666;
含有'!= '; select * from tb1 where name != 'zgc';
特别的:如果是主键,还是会走索引;select * from tb1 where nid != 123;
含有'>';select * from tb1 where name > 'zgc';
特别的:如果是主键或者索引是整数类型,则还是会走索引
# select * from tb1 where nid > 123;
# select * from tb1 where name > 123;
含有'order by';select email from tb1 order by name desc;
当根据索引排序时,选择的映射如果不是索引,则不走索引
特别的:如果对主键排序,则还是走索引:
# select * from tb1 order by nid desc;#组合索引最左前缀
如果组合索引为:(name,email)
name and email # 使用索引
name # 使用索引
email # 不使用索引
在对name做了唯一索引前提下,简述以下区别:
select * from tb where name = ‘小明’
select * from tb where name = ‘小明’ limit 1
没做唯一索引的话,前者查询会全表扫描,效率低些
limit 1,只要找到对应一条数据,就不继续往下扫描.
然而 name 字段添加唯一索引了,加不加limit 1,意义都不大;
1000w条数据,使用limit offset 分页时,为什么越往后翻越慢?如何解决?
例如:
#limit 100000,20; 从第十万条开始往后取二十条,
#limit 20 offset 100000; limit后面是取20条数据,offset后面是从先扫描前10w行,然后从10W条数据开始读
因为当一个数据库表过于庞大,LIMIT offset, length中的offset值过大,则SQL查询语句会非常缓慢
--------------------------------------------------------------------------
'优化一'
先查看主键,再分页:
select * from tb where id in (select id from tb where limit 10 offset 30)
--------------------------------------------------------------------------
'优化二'
记录当前页,数据、ID、最大值和最小值(用于where查询)
在翻页时,根据条件进行筛选,筛选完毕后,再根据 limit offset 查询
select * from(select * from tb where id > 2222) as B limit 10 offset 0;
# 如果用户自己修改页码,也可能导致变慢,此时可以对 url 页码进行加密,例如rest framework
--------------------------------------------------------------------------
'优化三'
可以按照当前业务需求,看是否可以设置只允许看前200页;
一般情况下,没人会咔咔看个几十上百页的;
MySQL中InnoDB引擎的行锁是通过加在什么上完成(或称实现)的?
InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!
InnoDB存储引擎MVCC的实现策略
MVCC的实现,通过保存数据在某个时间点的快照来实现的。这意味着一个事务无论运行多长时间,在同一个事务里能够看到数据一致的视图。根据事务开始的时间不同,同时也意味着在同一个时刻不同事务看到的相同表里的数据可能是不同的。
innodb:在每一行数据中额外保存两个隐藏的列:当前行创建时的版本号和删除时的版本号(可能为空,其实还有一列称为回滚指针,用于事务回滚,不在本文范畴)。这里的版本号并不是实际的时间值,而是系统版本号。每开始新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询每行记录的版本号进行比较。
每个事务又有自己的版本号,这样事务内执行CRUD操作时,就通过版本号的比较来达到数据版本控制的目的。
索引与锁有什么关系?
没有建立索引的话我们在进行数据选取或者定位的时候是通过全表扫描的形式来进行的,比如存在这样一张表user(id,name,phone,address);并且这张表中并没有任何索引,那么sql:delete from user where name='张三' 这样一个语句是如何定义到张三这个记录的,因为没有索引,所以在数据库实现的时候是对整张表进行扫描的,那么数据库是不是会把整张表锁定起来。
在mysql中的锁看起来是很复杂的,因为有一大堆的东西和名词:排它锁,共享锁,表锁,页锁,间隙锁,意向排它锁,意向共享锁,行锁,读锁,写锁,乐观锁,悲观锁,死锁。这些名词有的博客又直接写锁的英文的简写--->X锁,S锁,IS锁,IX锁,MMVC...
对于UPDATE、DELETE、INSERT语句,InnoDB会自动给涉及数据集加排他锁(X)
MyISAM在执行查询语句SELECT前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预
数据库事务有不同的隔离级别,不同的隔离级别对锁的使用是不同的,锁的应用最终导致不同事务的隔离级别
MVCC(Multi-Version Concurrency Control)多版本并发控制,可以简单地认为:MVCC就是行级锁的一个变种(升级版)。
事务的隔离级别就是通过锁的机制来实现,只不过隐藏了加锁细节
在表锁中我们读写是阻塞的,基于提升并发性能的考虑,MVCC一般读写是不阻塞的(所以说MVCC很多情况下避免了加锁的操作)
MVCC实现的读写不阻塞正如其名:多版本并发控制--->通过一定机制生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取。从用户的角度来看,好像是数据库可以提供同一数据的多个版本。
表中字段建立索引应该遵循几个原则:
- 1)越小的数据类型通常更好:越小的数据类型通常在磁盘、内存中都需要更少的空间,处理起来更快。
- 2)简单的数据类型更好:整型数据比起字符,处理开销更小,因为字符串的比较更复杂,处理起来也更耗时。
- 3)尽量避免NULL:应该指定列为NOT NULL。含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值。
- 4)对非唯一的字段,例如“性别”这种大量重复值的字段,增加索引也没有什么意义,所以索引的建立应当更多的选取唯一性更高的字段。
1、列举常见的关系型数据库和非关系型都有那些?
关系型:sqllite、db2、oracle、access、SQLserver、MySQL
# 注意:sql语句通用,需要有表结构
非关系型:mongodb、redis、memcache
# 非关系型数据库是key-value存储的,没有表结构。
2、MySQL常见数据库引擎
MySQL有多种存储引擎:MyISAM、InnoDB、MERGE、MEMORY(HEAP)、BDB(BerkeleyDB)、EXAMPLE、FEDERATED、ARCHIVE、CSV、BLACKHOLE
3、MyISAM 和 InnoDB 的区别
1)事务支持:
MyISAM:强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快,但是不提供事务支持。
InnoDB:提供事务支持事务,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。2)MyISAM适合查询以及插入为主的应用,InnoDB适合频繁修改以及涉及到安全性较高的应用。
3)InnoDB支持外键,MyISAM不支持。InnoDB支持MVCC(多版本并发控制), 而MyISAM不支持。
4)从MySQL5.5.5以后,InnoDB是默认引擎。
5)MyISAM支持全文类型索引,而InnoDB不支持全文索引。
6)InnoDB中不保存表的总行数,select count(*) from table时,InnoDB需要扫描整个表计算有多少行,但MyISAM只需简单读出保存好的总行数即可。注:当count(*)语句包含where条件时MyISAM也需扫描整个表。
7)对于自增长的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中可以和其他字段一起建立联合索引。
8)清空整个表时,InnoDB是一行一行的删除,效率非常慢。MyISAM则会重建表。MyisAM使用delete语句删除后并不会立刻清理磁盘空间,需要定时清理,命令:
OPTIMIZE table dept;
9)InnoDB支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like ‘%lee%’)
10)存储结构:
MyISAM:每个MyISAM在磁盘上存储成三个文件。第一个文件的名字以表的名字开始,扩展名指出文件类型。.frm文件存储表定义。数据文件的扩展名为.MYD (MYData)。索引文件的扩展名是.MYI (MYIndex)。
InnoDB:所有的表都保存在同一个数据文件中(也可能是多个文件,或者是独立的表空间文件),InnoDB表的大小只受限于操作系统文件的大小,一般为2GB11)表主键:
MyISAM:允许没有任何索引和主键的表存在,索引都是保存行的地址。
InnoDB:如果没有设定主键或者非空唯一索引,就会自动生成一个字节的主键(用户不可见),数据是主索引的一部分,附加索引保存的是主索引的值。12)可移植性、备份及恢复:
MyISAM:数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作。
InnoDB:免费的方案可以是拷贝数据文件、备份 binlog,或者用 mysqldump,在数据量达到几十G的时候就相对痛苦了应用场景:
- MyISAM不支持事务处理等高级功能,但它提供高速存储和检索,以及全文搜索能力。如果应用中需要执行大量的SELECT查询,那么MyISAM是更好的选择。
- InnoDB用于需要事务处理的应用程序,包括ACID事务支持。如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能。一般都选用InnoDB
Mysql中有哪几种锁?
表锁:select * from tb for update;(锁:for update)
行锁:select id ,name from tb where id=2 for update;(锁:for update)
- MyISAM支持表锁,InnoDB支持表锁和行锁,默认为行锁
- 表级锁:开销小,加锁快,不会出现死锁。锁定粒度大,发生锁冲突的概率最高,并发量最低
- 行级锁:开销大,加锁慢,会出现死锁。锁力度小,发生锁冲突的概率小,并发度最高
3、简述数据三大范式?
据库的三大特性:
'实体':表
'属性':表中的数据(字段)
'关系':表与表之间的关系
----------------------------------------------------
数据库设计三大范式:
第一范式(1NF):字段具有原子性,不可再分。(所有关系型数据库系统都满足第一范式数据库表中的字段都是单一属性的,不可再分)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。要求数据库表中的每个实例或行必须可以被惟一地区分。通常需要为表加上一个列,以存储各个实例的惟一标识。这个惟一属性列被称为主关键字或主键。
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。
所以第三范式具有如下特征:
1. 每一列只有一个值
2. 每一行都能区分。
3. 每一个表都不包含其他表已经包含的非主关键字信息。
6、简述数据库设计中一对多和多对多的应用场景?
一对一关系示例:
一个学生对应一个学生档案材料,或者每个人都有唯一的身份证编号。
一对多关系示例:(下拉单选)
一个学生只属于一个班,但是一个班级有多名学生。
多对多关系示例:(下拉多选)
一个学生可以选择多门课,一门课也有多名学生。
7、如何基于数据库实现商城商品计数器?
参考:点击查看
8、常见SQL(必备)
详见:点击查看
9、简述触发器、函数、视图、存储过程?
触发器:
对数据库某个表进行【增、删、改】前后,自定义的一些SQL操作
函数:
在SQL语句中使用的函数 #例如:select sleep(2)
聚合函数:max、sam、min、avg
时间格式化:date_format
字符串拼接:concat
自定制函数:(触发函数通过 select)
视图:
对某些表进行SQL查询,将结果实时显示出来(是虚拟表),只能查询不能更新
存储过程:
将提前定义好的SQL语句保存到数据库中并命名;以后在代码中调用时直接通过名称即可
参数类型:in、out、inout
13、MySQL常见的函数?
'当前时间'
select now();
'时间格式化'
select DATE_FORMAT(NOW(), '%Y(年)-%m(月)-%d(日) %H(时):%i(分):%s(秒)')
'日期加减'
select DATE_ADD(DATE, INTERVAL expr unit)
select DATE_ADD(NOW(), INTERVAL 1 DAY) #当前日期加一天
\expr:正数(加)、负数(减)
\unit:支持毫秒microsecond、秒second、小时hour、天day、周week、年year
'类型转换'
cast( expr AS TYPE)
select CAST(123 AS CHAR)
'字符串拼接'
concat(str1,str2,……)
select concat('hello','2','world') --> hellow2world
'聚合函数'
avg() #平均值
count() #返回指定列/行的个数
min() #最小值
max() #最大值
sum() #求和
group_concat() #返回属于一组的列值,连接组合而成的结果
'数学函数'
abs() #绝对值
bin() #二进制
rand() #随机数
15、如何开启慢日志查询?
可以通过修改配置文件开启
slow_query_log=ON # 是否开启慢日志记录
long_query_time=2 # 时间限制,超过此时间,则记录
slow_query_log_file=/usr/slow.log # 日志文件
long_queries_not_using_indexes=ON # 是否记录使用索引的搜索
16、数据库导入导出命令(结构+数据)?
# 导出:
mysqldump --no-defaults -uroot -p 数据库名字 > 导出路径
'--no-defaults':解决“unknown option --no-beep”报错
# 导入:
1、mysqldump -uroot -p 数据库名称 < 路径
2、进入数据库; source + 要导入数据库文件路径
数据库优化方案?
详细可参考:https://blog.csdn.net/fenglepeng/article/details/103400418
1、创建数据表时把固定长度的放在前面
2、将固定数据放入内存:choice字段(django中用到,1,2,3对应相应内容)
3、char不可变,varchar可变
4、联合索引遵循最左前缀(从最左侧开始检索)
5、避免使用 select *
6、读写分离:
#利用数据库的主从分离:主,用于删除、修改、更新;从,用于查
#实现:两台服务器同步数据
\原生SQL:select * from db.tb
\ORM:model.User.object.all().using('default')
\路由:db router
7、分库
# 当数据库中的表太多,将某些表分到不同数据库,例如:1W张表时
# 代价:连表查询跨数据库,代码变多
8、分表
# 水平分表:将某些列拆分到另一张表,例如:博客+博客详情
# 垂直分表:将某些历史信息,分到另外一张表中,例如:支付宝账单
9、加缓存
# 利用redis、memcache(常用数据放到缓存里,提高取数据速度)
# 缓存不够可能会造成雪崩现象
10、如果只想获取一条数据
select * from tb where name = 'zgc' limit 1;
19、简述MySQL的执行计划?
详细可参考:https://blog.csdn.net/fenglepeng/article/details/103392319
# explain + SQL语句
# SQL在数据库中执行时的表现情况,通常用于SQL性能分析,优化等场景。
'explain select * from rbac_userinfo where id=1;'
24、简述数据库读写分离?
# 利用数据库的主从分离:主,用于删除、修改、更新;从,用于查
#实现:两台服务器同步数据(减轻服务器的压力)
原生SQL: select * from db.tb
ORM:model.User.object.all().using('default')
路由:db router
25、简述数据库分库分表?(水平、垂直)
# 1、分库
当数据库中的表太多,将某些表分到不同数据库,例如:1W张表时
代价:连表查询跨数据库,代码变多
# 2、分表
水平分表:将某些列拆分到另一张表,例如:博客+博客详情
垂直分表:将某些历史信息,分到另外一张表中,例如:支付宝账单
char和varchar、Varbinary 存储字符的区别?
char使用固定长度的空间进行存储,char(4)存储4个字符,根据编码方式的不同占用不同的字节,gbk编码方式,不论是中文还是英文,每个字符占用2个字节的空间,utf8编码方式,每个字符占用3个字节的空间。
如果需要存储的字符串的长度跟所有值的平均长度相差不大(定值),适合用char。
对于经常改变的值,char优于varchar,原因是固定长度的行不容易产生碎片。对于很短的列,char优于varchar,原因是varchar需要额外一个或两个字节存储字符串的长度。
varchar保存可变长度的字符串,使用额外的一个或两个字节存储字符串长度,varchar(10),除了需要存储10个字符,还需要1个字节存储长度信息(10),超过255的长度需要2个字节来存储
binary保存二进制字符串,它保存的是字节而不是字符,没有字符集限制
binary(8)可以保存8个字符,每个字符占1个字节,共占8个字节(01串)
delete、drop、truncate区别
- truncate 和 delete只删除数据,不删除表结构 ,drop删除表结构,并且释放所占的空间。
- 删除数据的速度,drop> truncate > delete
- delete属于DML语言,需要事务管理,commit之后才能生效。drop和truncate属于DDL语言,操作立刻生效,不可回滚。
- 使用场合:
- 当你不再需要该表时, 用 drop;
- 当你仍要保留该表,但要删除所有记录时, 用 truncate;
- 当你要删除部分记录时(always with a where clause), 用 delete.
Float、Decimal 存储金额的区别?
浮点数计算都不准(只要不是2的整数倍都会有问题)。decimal存储其实是string类型存储。
Datetime、Timestamp 存储时间的区别?
对于TIMESTAMP,它把客户端插入的时间从当前时区转化为UTC(世界标准时间)进行存储。查询时,将其又转化为客户端当前时区进行返回。对于跨时区的业务,TIMESTAMP更为合适。
而对于DATETIME,不做任何改变,基本上是原样输入和输出。
HAVING 子句 和 WHERE的异同点?
语法上:where 用表中列名,having用select结果别名
影响结果范围:where从表读出数据的行数,having返回客户端的行数
索引:where 可以使用索引,having不能使用索引,只能在临时结果集操作
where后面不能使用聚集函数,having是专门使用聚集函数的。
mysql 备份
mysql的复制原理以及流程。
Mysql内建的复制功能是构建大型,高性能应用程序的基础。将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重新执行一遍来实现的.
复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。 当一个从服务器连接主服务器时,它通知主服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。 过程如下
主服务器把更新记录到二进制日志文件中。
从服务器把主服务器的二进制日志拷贝到自己的中继日志(replay log)中。
从服务器重做中继日志中的时间,把更新应用到自己的数据库上。
mysql支持的复制类型?
基于语句的复制: 在主服务器上执行的SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。 一旦发现没法精确复制时,会自动选着基于行的复制。
基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍. 从mysql5.0开始支持
混合类型的复制: 默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。
MySQL的binlog有有几种录入格式?分别有什么区别?
有三种格式,statement,row和mixed.
statement模式下,记录单元为语句.即每一个sql造成的影响会记录.由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制.
row级别下,记录单元为每一行的改动,基本是可以全部记下来但是由于很多操作,会导致大量行的改动(比如alter table),因此这种模式的文件保存的信息太多,日志量太大.
mixed. 一种折中的方案,普通操作使用statement记录,当无法使用statement的时候使用row.
MySQL中空值和NULL的区别?
- 空值(”)是不占用空间的,判断空字符用 = ” 或者 <> ” 来进行处理。
- NULL值是未知的,且占用空间,不走索引;判断 NULL 用 IS NULL 或者 is not null ,SQL 语句函数中可以使用 ifnull ()函数来进行处理。
- 无法比较 NULL 和 0;它们是不等价的。
- 无法使用比较运算符来测试 NULL 值,比如 =, <, 或者 <>。
NULL
值可以使用<=>
符号进行比较,该符号与等号作用相似,但对NULL
有意义。- 进行 count ()统计某列的记录数的时候,如果采用的 NULL 值,会别系统自动忽略掉,但是空值是统计到其中。