巩固基础,砥砺前行 。
只有不断重复,才能做到超越自己。
能坚持把简单的事情做到极致,也是不容易的。
1.检查是否走了索引,如果没有则优化SQL利用索引
2.检查所利用的索引,是否是最优索引
3.检查所查字段是否都是必须的,是否查询了过多字段,查出了多余数据
4.检查表中数据是否过多,是否应该进行分库分表了
5.检查数据库实例所在机器的性能配置,是否太低,是否可以适当增加资源
按锁粒度分类:
1.行锁:锁某行数据,锁粒度最小,并发度高
2.表锁:锁整张表,锁粒度最大,并发度低
3.间隙锁:锁的是一个区间
还可以分为:
1.共享锁:也就是读锁,一个事务给某行数据加了读锁,其他事务也可以读,但是不能写
2.排它锁:也就是写锁,一个事务给某行数据加了写锁,其他事务不能读,也不能写
还可以分为:
1.乐观锁:并不会真正的去锁某行记录,而是通过一个版本号来实现的
2.悲观锁:上面所的行锁、表锁等都是悲观锁
在事务的隔离级别实现中,就需要利用所来解决幻读
B树的特点:
1.节点排序
2.一个节点了可以存多个元素,多个元素也排序了
B+树的特点:1.拥有B树的特点2.叶子节点之间有指针
3.非叶子节点上的元素在叶子节点上都冗余了,也就是叶子节点中存储了所有的元素,并且排好顺序
Innodb通过Buffer Pool,LogBuffer,Redo Log,Undo Log来实现事务,以一个update语句为例:1.Innodb在收到一个update语句后,会先根据条件找到数据所在的页,并将该页缓存在Buffer Pool中2.执行update语句,修改Buffer Pool中的数据,也就是内存中的数据
3.针xupdate语句生成一个RedoLog对象,并存入LogBuffer中
4.针对update语句生成undolog日志,用于事务回滚
5.如果事务提交,那么则把RedoLog对象进行持久化,后续还有其他机制将Buffer Pool中所修改的数据页持久化到磁盘中
6.如果事务回滚,则利用undolog日志进行回滚
left join中关于where和on条件的几个知识点:
1.多表left join是会生成一张临时表,并返回给用户
2.where条件是针对最后生成的这张临时表进行过滤,过滤掉不符合where条件的记录,是真正的不符合就过滤掉。
3.on条件是对left join的右表进行条件过滤,但依然返回左表的所有行,右表中没有的补为NULL
4.on条件中如果有对左表的限制条件,无论条件真假,依然返回左表的所有行,但是会影响右表的匹配值。也就是说on中左表的限制条件只影响右表的匹配内容,不影响返回行数。
结论:
1.where条件中对左表限制,不能放到on后面
2.where条件中对右表限制,放到on后面,会有数据行数差异,比原来行数要多
1.create database aa;
2.show create database aa\G;
3.drop database aa; 删除数据库,mysql是不会有提示的,而且不能回复
4.show engines; sopport 表示该数据引擎是否能使用,yes表示可以,no表示不能,default表示该引擎是当前的默认引擎。
5.mysql数据库引擎介绍:
5.1 InnoDB:
它是事务型数据库的首选引擎,支持事务安全表(提供了提交、回滚、奔溃的恢复能力),支持行锁和外键。
在mysql5.5之后,他就是mysql的默认数据库引擎。 InnoDB 锁定在行级 并且 也在select语句中提供了一个类似oracle的非锁定读。
InnoDB能够处理大数据量的数据。
InnoDB存储引擎完全和mysql服务器整合,InnoDB为在主内存中缓存数据和索引而维护他自己的缓存池。
InnoDB中的表和缩影存储在一个逻辑空间中,表中可以包含多个数据文件或者原始磁盘分区。 这一点和 MyISAM不同,MyISAM单个表中存放在分离的文件中。
InnoDB表可设置任何尺寸。
InnoDB支持外键完整性约束。存储表中的数据时,按照表中的住建顺序存放,如果没有主键,他会为每行数据创建一个6B的rowId,以此作为行记录的主键。
InnoDB用在需要高性能的大型数据库的地方。
InnoDB不会创建目录,MySQL 在她的数据目录下创建一个可以动态扩容的 名为ibdata1的 大小为10M的数据文件,创建两个5M的数据库日志文件,ib_logfile0和ib_logfile01.
5.2 MyISAM
MyISAM具有较高的查询、插入速度。不支持事务,它是mysql5.5之前的版本默认的数据库。
支持大文件在支持大文件的系统上被支持。
当insert update delete 混合使用时,动态尺寸的行产生更少的碎片。
单表最大索引数是64,可以通过编译改变.每个索引最大的列是16列
最大的键长是100B ,可以通过编译改变,
blob和text 列可以被索引
null值可以出现在索引中
所有的键值以高字节优先被存储以允许一个更高的索引压缩
表中的自增长列的内部处理,insert 和 update 操作自动更新这一列,这使得自增长(auto_increment)列更快。在序列顶的值悲伤出后就不再使用了
可以把数据文件和索引文件放在不同的位置
每个字符列可以有不同的字符集
有varchar的表可以固定或者动态记录长度
varchar 和 char 列可以多达64K
使用MyISAM创建数据库,产生三个文件,文件名以表名开始,.frm 文件存储表定义 、.myd 文件存储数据 、.myi存储索引
5.3 memory
它把表中的数据存放在内存中
memory表中可以有32个索引、每个索引可以有16列,以及500B的最大键长度
支持存储hash和bree索引
可以在memory表中有非唯一键
不支持blob和text
支持自增长列和对包含null值列的索引
memory表在所有客户端之间共享
1.在创建表的时候定义主键
create table aa{
id int(10) primary key auto_incremnt,
name varchar(10)
};
指定索引从哪里开始:alter table aa AUTO_INCREMENT=123456
2.定义完列之后申明主键
create table aa{
id int(10) ,
name varchar(10),
primary key(id)
};
alter table aa add primary key(id);
一堆约束 外键约束 非空约束 唯一性约束
显示表字段以及类型 desc aa
显示建表语句 show create table aa\G
7.修改表名 alter table aa rename bb
9.修改列名 alter table aa change name newname varchar(10)
10 添加列 alter table aa add sex char(1) [first | after columnlname]
11 添加约束:alter table aa add nickname varchar(30) not null
12 删除字段:alter table aa drop nickname
13 修改字段的位置:alter table aa modify name varchar(10) first | alter name
14 更改数据库引擎:alter table aa engine = MyISAM
15 删除表的外键:alter table aa drop foreign key name
16 drop table if exist aa
17 删除有关联的表:首先删除关联关系,然后在删除对应的表:alter table aa drop foreign key fk_name; drop table aa;
MySQL 支持多种数据类型,主要有 数值类型、日期/时间、字符串等
数值类型:整数类型:tinyint(1)、smallint(2)、mediumint(3)、int(4)、bigint(8);浮点数据类型有:float(4)、double(8) ;指定小数类型:decimal(M,D) M+2个字节。无论是定点还是浮点,如果用户指定的精度超出精度范围,则会四舍五入进行处理。
时间日期类型:year(YYYY)、time(HH:MM:SS)、date(YYYY-MM-DD)、datetime(YYYY-MM-DD HH:MM:SS)、timestamp(YYYY-MM-DD HH:MM:SS)
字符串类型:char、varchar、binary、varbinary、blob、text、enum、set。字符串类型分为文本类型和二进制类型。
float(5,1)–>float(5.12) = 5.1
double(5,1)->double(5.15) = 5.2
decimal(5,1)->decimal(5.123) = 5.1
声明:写这个玩意,仅仅是为了复习看看。仅此而已。
索引,老生常谈。就是为了快,用空间换时间的。
索引是在存储引擎中实现的,每种存储引擎的所应都不一定相同,并且每种存储引擎也不一定支持所有的索引类型。mysql中的缩影的存储类型有两种btree和hash。myisam和innodb只支持btree。memory和heap可以支持btree和innodb。每个表都支持至少16个索引,每个表索引长度最少256字节。
1、通过创建唯一索引,可以保证数据库中的每条记录的唯一性
2、可以加快查询速度
3、在实现数据的参考完整性方面,可以加快表之间的连接
4、在使用分组和排序是,可以显著减少查询中分组和排序的时间
1、创建和维护缩影需要耗费时间,并且随着数据量的增加所耗费的时间也会增加
2、索引需要占用存储空间,物理空间,如果有大量的缩影,索引文件可能比数据文件更快达到最大尺寸
3、对表进行crud操作时,索引需要动态的移动,这样减低了数据的维护速度
1、普通索引和唯一索引
2、单列索引和组合索引
3、全文索引
全文索引可以在char、varchar、text类型上创建,mysql上只有myisam引擎可以创建全文索引
4、空间索引
mysql上只有myisam引擎可以创建空间索引
索引设计不合理或者缺少索引都会对数据库和应用程序的性能造成障碍。高效的索引对千获得良好的性能非常重要。设计索引时,应该考虑以下准则:
如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length.
参考MySQL手册 13.1.4. CREATE INDEX语法
对于CHAR和VARCHAR列,只用一列的一部分就可创建索引。创建索引时,使用col_name(length)语法,对前缀编制索引。前缀包括每列值的前length个字符。BLOB和TEXT列也可以编制索引,但是必须给出前缀长度。
此处展示的语句用于创建一个索引,索引使用列名称的前10个字符。
CREATE INDEX part_of_name ON customer (name(10));
因为多数名称的前10个字符通常不同,所以此索引不会比使用列的全名创建的索引速度慢很多。另外,使用列的一部分创建索引可以使索引文件大大减小,从而节省了大量的磁盘空间,有可能提高INSERT操作的速度
MySQL 支持多种方法在单个或多个列上创建索引:
-- 建表的时候指定索引
CREATE TABLE aa(
ID INT NOT NULL,
info VARCHAR(255) NULL,
comment VARCHAR (255) NULL,
year_publication YEAR NOT NULL,
INDEX(year_publication)
)
--创建唯一索引
UNION INDEX(year_publication)
--创建全文索引
FULLTEXT INDEX FullTxtidx (info)
SHOW INDEX FROM TABLE_NAME;
Table: book Non_unique: 1
Key_nam : year_publication
Seq_in_index: 1
Column_name: year_publication
Collation: A
Cardinality : 0
Sub_part: NULL
Packed: NULL Null:
Index_type: BTREE
Comment:
Index comment:
其中各个主要参数的含义为:
ALTER TABLE TABLE_NAME ADD INDEX INDEX_NAME(CLOUMN(INDEX_LENGTH))
CREATE INDEX INDEX_NAME(CLOUMN(INDEX_LENGTH))
有两种方式
1. ALTER TABLE TABLE_NAME DROP INDEX INDEX_NAME;
2. DROP INDEX INDEX_NAME ON TABLE_NAME;
数字函数、字符串函数、时间日期函数、条件函数、系统函数、加密函数、其他特殊函数
数字函数
2.pi() 圆周率
mod(x,y) 余数、sprt()
获取整数函数:ceil() ceiling() floor()
ceil(-3.35) = -3
ceilIng(3.35) = 4
floor(-3.35) = -4
floor(3.35) = 3
随机数函数 rand()[0,1] rand(X)
四舍五入:round() round(x,y) y表示小数点后保留几位 truncate()
符号函数:sign(x)
sign(-21) = -1
sign(0) = 0
sign(21) = 1
8. 幂运算:pow() power() exp()
字符串函数
1.char_length() 字符个数
2.length() 字节长度
concat_ws(‘-’,1,1) = 1-1
concat_ws(‘-’,1,null) = 1-
4.字符串替换: insert(s1,x,len,sr) 索引是从1开始
6.获取指定长度的字符串:left(s,len)、right(s,len)
填充 lpad(s1,len.s2) rpad()
删除空格 trim ltrin rtrim
删除指定字符串 trim(s2 from string)
重复生成字符串repeat(s,n)
11, 空格函数:space(n) ;替换replace(s,s1,s2)
12.字符串大小比较:strcmp(s1,s2) 返回 -1,0,1
13.匹配字符串位置:locate(str,s) 返回索引位置,索引从0开始;positoin(str1 in str);instr(str,str1)
reverse()
返回指定位置的字符串函数:elt()
elt(1,1,b,c) = a
elt(3,a,b) = null
16 返回指定字符串位置的函数:field()
field(s,s1,s2)
field(‘hi’,a,b,‘hi’) = 3
field(‘hi’,‘hihi’,‘hh’) = 0
17 返回字符串位置的函数:find_in_set(s1,s2) s1 在s2中出现的索引位置
18 获取字符串函数:make_set
时间日期
1.curdate() cur_date() curdate()+0
2.curtime() cur_time() curtime()+0
3.current_timestamp() localdate() now() sysdate()
5.uct_date() 世界标准时间
6.month() monthname()
7.dayname() dayofweek() 注意:1表示周日 7表示周6 weekday() 表示工作日索引。0表示周一
8.week(date) 查询日期是一年中的第几周 ,week(date,modle):modle 表示一周的第一天是周几,默认是0,0标识 一周第一天是周日 ;weekofyear(date) 查询日期是一年中的第几周
9.dayofyear(date) 、dayofmonth(date) 时间在一年、一月中的第几天
11.extract(type from date) :type可以为 year 、year_month、year_minute
12 时间和秒转换:time_to_sec() sec_to_time()
13 计算时间和日期的函数:
date_add()、adddate() :时间加法操作:date_add(date,interval 数量 单位) 单位可以是 年月日时分秒
date_sub()、subdate():时间减法操作:date_add(date,interval 数量 单位) 单位可以是 年月日时分秒
addtime(date,express) :addtime(‘2020-01-01 11:00:00’ ,‘1:00:00’) 加了一个小时 ;subtime() 同理 addtime(‘2020-01-01 12:00’,‘24:00’)
date_diff(d1,d2) : 返回天数
条件判断函数
2.ifnull(a,b)
系统信息函数
select version()
select connection_id()
show processlist
select database() ,schema()
select user(),current_user(),system_user(),session_user()
select charset(‘123’) 获取字符集
select last_insert_id()
加密函数、
password()
md5()
encode(str,pwd_str)
decode(str,pwd_str)
其他函数
cast() convert()
是一个单独的、存储在磁盘上的数据库结构,它 们包含着对数据表里所有记录的引用指针
MySQL 中索引的存储类型有两种: BTREE 和 HASH, 具体和表的存储引擎相关;
MyISAM 和InnoDB 存储引擎只支持BTREE 索引; MEMORY/HEAP 存储引擎可以支持 HASH
和 BTREE 索引。
索引的优点主要有以下几条:
通过创建唯一索引, 可以保证数据库表中每一行数据的唯一性。
可以大大加快数据的查询速度, 这也是创建索引的最主要的原因。
在实现数据的参考完整性方面, 可以加速表和表之间的连接。
在使用分组和排序子句进行数据查询时, 也可以显著减少查询中分组和排序的时间。
增加索引也有许多不利,主要表现在如下几个方面:
创建索引和维护索引要耗费时间, 并且随着数据量的增加所耗费的时间也会增加。
索引需要占磁盘空间, 除了数据表占数据空间之外, 每一个索引还要占一定的物理空间,如果有大量的索引,索引文件可能比数据文件更快达到最大文件尺寸。
当对表中的数据进行增加、删除和修改的时候, 索引也要动态地维护, 这样就降低了数据的维护速度。
1.普通索引和唯—索引
2.单列索引和组合索引
3.全文索引
4.空间索引
索引的设计原则
索引并非越多越好
避免对经常更新的表进行过多的索引
数据量小的表最好不要使用索引
在条件表达式中经常用到的不同值较多的列上建立索引, 在不同值很少的列上不要建立索引
当唯一性是某种数据本身的特征时,指定唯一索引。使用唯一索引需能确保定义的列的数据完整性,以提高查询速度
在频繁进行排序或分组(即进行group by 或 order by 操作)的列上建立索引
create index index_1 on by_his_user(USER_NAME);
(1)select_type 行指定所使用的SELECT查询类型,这里值为SIMPLE, 表示简单的SELECT,
不使用UNION 或子查询。其他可能的取值有: PRIMARY、UNION、SUBQUERY 等。
(2)table 行指定数据库读取的数据表的名字, 它们按被读取的先后顺序排列。
(3)type 行指定了本数据表与其他数据表之间的 关联关系, 可能的取值有 system、const、
eq_ref、 ref、 range、 index 和 All。
(4)possible_keys 行给出了 MySQL 在搜索数据记录时可选用的各个索引。
(5)key 行是 MySQL 实际选用的索引。
(6)key—len 行给出索引 按字节计算的长度, ke y_len 数值越小, 表示越快。
(7)ref 行给出了关联关系中另 一个数据表里的数据列的名字。
(8)rows 行是 MySQL 在执行这个查询时预计会从这个数据表里读出的数据行的个数。
extra 行提供了与关联操作有关的信息
性能下降SQL慢,执行时间长,等待时间长:
查询语句写的烂
索引失效???
关联查询太多join
服务器调优及各个参数设置
left join
right join
inner join
left join on where b.XXX is null
right join on where a.XXX is null
full outer join
full outer join where a.XXX is null or b.XXX is null
数据库迁移就是把数据从一个系统移动到另一个系统上
主版本号 相同的 MySQL 数据库之间进行数据库移动
eg:将www.abc.com 主机上的 MySQL 数据库全部迁移到 www.bcd.com 主机上。在
www.abc.com 主机上执行的命令如下
mysqldump -h www.abc.com -uroot -ppassword dbname |
mysql -h www.bcd.com -uroot -ppassword
MySQLdump 导入的数据直接通过管道符 " I " 传给 MySQL 命令导入的主机
www.bcd.com 数据库中, dboame 为需要迁移的数据库名称, 如果要迁移全部的数据库 , 可使用参数–all-databases
将旧版本数据库中的数据备份出来,然后导入到新版本的数据库中
可以使用naviat Premium工具进行不同数据库之间数据的迁移
如果数据库通过复制数据库文件备份,可以直接复制备份的文件到 MySQL 数据目录下实现恢复。
通过这种方式恢复时,必须保存备份数据的数据库和待恢复的数据库服务器的主版本号相同。而且这种方式只对 MyISAM 引擎的表有效,对于 InnoDB 引擎的表不可用。
执行恢复以前关闭MySQL服务,将备份的文件或目录覆盖 MySQL 的 data 目录,启动MySQL 服务。对于 Linux/Unix 操作系统来说, 复制完文件需要将文件的用户和组更改为
MySQL 运行的用户 和组,通 常用户是 MySQL, 组也是 MySQ
Explain:使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的,能查看哪些索引被使用,表的执行顺序。
explain select* from book where year_publication=l990 \G
id: 1
select_type: SIMPLE
table : book
type: ref
possible_keys: year_publication
key: year_publication
key_len: 1
ref: const
rows: l
Extra:
三种情况:
id相同,执行顺序由上至下
id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
id相同不同,同时存在
表示查询中每个select子句的类型
(1) SIMPLE(简单SELECT,不使用UNION或子查询等)
(2) PRIMARY(子查询中最外层查询,查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY)
(3) UNION(UNION中的第二个或后面的SELECT语句)
(4) DEPENDENT UNION(UNION中的第二个或后面的SELECT语句,取决于外面的查询)
(5) UNION RESULT(UNION的结果,union语句中第二个select开始后面所有select)
(6) SUBQUERY(子查询中的第一个SELECT,结果不依赖于外部查询)
(7) DEPENDENT SUBQUERY(子查询中的第一个SELECT,依赖于外部查询)
(8) DERIVED(派生表的SELECT, FROM子句的子查询)
(9) UNCACHEABLE SUBQUERY(一个子查询的结果不能被缓存,必须重新评估外链接的第一行)
显示表名称或者别名
对表访问方式,表示MySQL在表中找到所需行的方式,又称“访问类型”。
常用的类型有: ALL、index、range、 ref、eq_ref、const、system、NULL(从左到右,性能从差到好)
ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行
index: Full Index Scan,index与ALL区别为index类型只遍历索引树
range:只检索给定范围的行,使用一个索引来选择行
ref: 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
eq_ref: 类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件
const、system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system
NULL: MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成
指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用(该查询可以利用的索引,如果没有任何索引显示 null)
key列显示MySQL实际决定使用的键(索引),必然包含在possible_keys中
如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)
列与索引的比较,表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
估算出结果集行数
该列包含MySQL解决查询的详细信息,有以下几种情况:
Using where:不用读取表中所有信息,仅通过索引就可以获取所需数据,这发生在对表的全部的请求列都是同一个索引的部分的时候,表示mysql服务器将在存储引擎检索行后再进行过滤
Using temporary:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询,常见 group by ; order by
Using filesort:当Query中包含 order by 操作,而且无法利用索引完成的排序操作称为“文件排序”
– 测试Extra的filesort
explain select * from emp order by name;
Using join buffer:改值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。
Impossible where:这个值强调了where语句会导致没有符合条件的行(通过收集统计信息不可能存在结果)。
Select tables optimized away:这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行
No tables used:Query语句中使用from dual 或不含任何from子句
mysqldump -uroot -p 数据库名称 表名 >aa.sql
eg:mysqldump -uroot -p course student >aa.sql
命令:mysqldump -uroot -p 数据库名称 >aa.sql
eg:mysqldump -uroot -p course >aa.sql
命令:mysqldump -uroot -p >aa.sql
eg:mysqldump -uroot -p --all-databases >aa.sql
命令:mysqldump -uroot -p --no-data [数据库名称] >aa.sql
eg:mysqldump -uroot -p --no-data [springbootv2][--all-databases] >aa.sql
命令:mysqldump -uroot -p --no-create-info [数据库名称] >aa.sql
eg:mysqldump -uroot -p --no-create-info [springbootv2][--all-databases] >aa.sql
命令:mysqldump -uroot -p --routines --triggers [数据库名称] >aa.sql
eg:mysqldump -uroot -p --routines --triggers [springbootv2][--all-databases] >aa.sql
命令:mysql -uroot -p <备份文件.sql
eg:mysql -uroot -p
命令:mysql> source 备份文件.sql
eg: mysql> source test.sql
事务是由一组SQL语句组成的逻辑处理单元,事务具有以下4个属性,通常简称为事务的ACID属性。
l 原子性(Atomicity):事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。
l 一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态。
这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性;
事务结束时,所有的内部数据结构(如B树索引或双向链表)也都必须是正确的。
l 隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。
这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然。
l 持久性(Durable):事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。
更新丢失(Lost Update)
当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,
就会发生丢失更新问题--最后的更新覆盖了由其他事务所做的更新。
例如,两个程序员修改同一java文件。每程序员独立地更改其副本,然后保存更改后的副本,这样就覆盖了原始文档。
最后保存其更改副本的编辑人员覆盖前一个程序员所做的更改。如果在一个程序员完成并提交事务之前,
另一个程序员不能访问同一文件,则可避免此问题。
脏读(Dirty Reads)
一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,
另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此做进一步的处理,
就会产生未提交的数据依赖关系。这种现象被形象地叫做”脏读”。
一句话:事务A读取到了事务B已修改但尚未提交的的数据,还在这个数据基础上做了操作。此时,如果B事务回滚,A读取
的数据无效,不符合一致性要求。
不可重复读(Non-Repeatable Reads)
一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!
这种现象就叫做“不可重复读”。
一句话:事务A读取到了事务B已经提交的修改数据,不符合隔离性
幻读(Phantom Reads)
一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”。
一句话:事务A读取到了事务B体提交的新增数据,不符合隔离性。
多说一句:幻读和脏读有点类似,
脏读是事务B里面修改了数据,
幻读是事务B里面新增了数据。
脏读”、“不可重复读”和“幻读”,其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。
数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在
一定程度上 “串行化”进行,这显然与“并发”是矛盾的。同时,不同的应用对读一致性和事务隔离程度的
要求也是不同的,比如许多应用对“不可重复读”和“幻读”并不敏感,可能更关心数据并发访问的能力。