数据库知识

事物的四个特性

事务(Transaction)是由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行逻辑单元。事务是DBMS中最基础的单位,事务不可分割。ACID:原子性、一致性、隔离性、持久性。

  1. A: 原子性(Atomicity)。原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响

  2. C:一致性(Consistency)。一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

    拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。

  3. I:隔离性(Isolation)。隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

  4. D:持久性(Durability)。持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

脏读、幻读和不可重复读

这几种情况在读取和写入数据库的时候会产生,事务虽然有原子性,但是读写的并发并不影响原子性,因此最终导致了以下的数据并发问题。解决这几种错误的数据库现象,需要了解数据库的事务隔离级别,下方有详细介绍。

  • 脏读:事务A读取的事务B中尚未提交的数据,如果事务B回滚,则A读取使用了错误的数据。比如我给你转了100万,但是我还没有提交,此时你查询自己账户,多了100万,很开心。然后我发现转错人了,回滚了事物。然后你100万就没了。 在过程中你查到了没有提交事物的数据(多出的100万),这就是脏读。
  • 不可重复读:指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值(这里主要指某一表项的修改),这是由于在查询间隔,被另一个事务修改并提交了。这里的不可重复读主要说的是数据库表的某一项,和幻读的区别在于幻读是数据库内表中的查询不一致。在某些情况下,不可重复读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主。但在另一些情况下就有可能发生问题,例如同一个事物前后两次查询同一个数据,期望两次读的内容是一样的,但是因为读的过程中,因为另一个事务写了该数据,导致不可重复读。
  • 幻读:在事务A的多次读取构成中,事务B对数据(这里主要指的是表内的插入操作)进行了新增操作,导致事务A多次读取的数据不一样,好像出现了幻觉一样。不可重复度是表项的update操作,幻读是对表内的insert操作。比如第一次读取表内是10个查询结果,在第二次查询之前,另一个事务加了一条(因为不是对同一个数据项写入,不是不可重复读),这时再次查询就变成了11个,不一致了。
  • 第一类事务丢失(回滚丢失):A和B在同时写一个数据,B事务已经提交,修改了数据,然后A事务因为某种原因回滚了,导致B事务的提交因A事务的回滚而丢失了。举例子来说,比如我有1000元。买一个东西,花了100元。然后我朋友给我转了1000元。理论上这两个事物(转账和买东西)正常的话,我应该还有1900元。 但是现在两个事物A和B同时进行,第一步都先查询我余额还有1000元,然后B事物给我转了1000元,提交了,理论上我还有2000元。然后我买东西,100元的,买到一半,我事物回滚,就回滚成了1000元(少了1000)。如果我不回滚,也提交了,我就还剩900元(也就是下面介绍的第二类事物丢失,覆盖丢失,也是少了1000)。
  • 第二类事务丢失(提交覆盖丢失):A和B同时执行事务,两个事务同时取到一个数据,B事务首先提交,但是A事务接下来又提交,这样就覆盖了B事务。

CSDN.数据库ACID四大特性及脏读,不可重复读,幻读,事物丢失

CSDN.对数据库幻读的理解

CSDN.数据库第一类第二类丢失更新

数据库的事务隔离级别

事务的隔离级别实际上就是用锁来处理并发操作中,对于数据读写之后的不一致情况。下方的加锁的等级从低到高,而且加锁越多,数据库的效率越低,因为如果串行化就没有并发了。

  1. 未提交读(Read uncommitted)。写操作加锁,读操作不加锁,禁止第一类丢失更新,但是其他数据并发问题还会发生。
  2. 提交读(Read committed)。写操作加写锁,读操作加读锁。禁止第一类丢失更新和脏读。指你已经开始读了数据,然后一个事物开始写,然后写的事物不提交的话,是不能进行读的事物,避免了脏读。
  3. 可重复读(Read repeatable)。对于读操作加读锁到事务结束,其他事务的更新操作只能等到事务结束之后进行。和提交 读的区别在于,提交读的读操作是加读锁到本次读操作结束,可重复读的锁粒度更大。禁止两类丢失更新,禁止脏读和不可 重复度,但是可能出现幻读.一个事物读的时候,我们把两次读看成整体,在读的过程中,不允许写的操作,这样就可以禁止不可重复读。就是两次读操作不允许其他事物。这是大部分关系数据库的默认隔离级别
  4. 序列化(Serializable)。对表级读和写加锁。读操作加表级读锁至事务结束。可以禁止幻读。

好好看看下边的博客,里面图片比较容易理解。

Blog.ZhuoQiLin 数据库的四大特性以及四个隔离级别和引发的问题

B树和B+树

B树

B树是2-3树的一种扩展,用于对数据的排序和快速查找(时间复杂度为O(logn))。B树是一颗多路平衡查找树,并且满足以下的定义,其中m是B树的阶数:

  1. 每个节点最多有m - 1个关键字(键值对)。
  2. 根节点最少可以只有1个关键字。
  3. 非根节点至少有m / 2个关键字。
  4. 每个节点中的所有关键字都按照从下到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的都大于它。
  5. 所有叶子节点都位于同一层,即根节点到每个叶子节点的长度都相同。
  6. 每一个节点都存有索引和数据(这点和B+树不一样,因此特别说明)。

B+树

相比于B树,B+树有两种类型的节点:内部节点(也称索引节点)和叶子节点。其中内部节点是不存储数据的,只存储索引,数据都存储在叶子节点。内部节点中的key都从小到大排列,左子树的key都更小,右子树都更大。叶子节点也是有序的。每个叶子节点都存有相邻叶子节点的指针,这样可以从一个叶子节点直接找到另一个叶子节点。父节点存有右孩子的第一个元组的索引。

插入操作简单来说,就是如果大于等于m个了,就将中间的作为索引放到父节点,然后右边多一个。

删除操作相比于B树更加容易,只需要从左右边兄弟节点结元素,并且修改父亲的索引即可,如果借不到,就合并,之后还是修改父亲索引。

Blog.SF 面试官问你B树和B+树,就把这篇文章丢给他

MySql常用语句

select Email
from Person
--使用group by将所有不同Email分组
group by Email
--having子句作为挑选Email分组的条件
having count(Email) > 1

select distinct p1.Email 
--自连接,将左边和右边的表一起查询
from Person as p1 inner join Person as p2
--条件是如下where子句
where p1.Email = p2.Email and p1.Id != p2.Id

select A.Name as Customers
--左连接,即便右边是空的也连接
from Customers as A left join Orders as B
--on语句,条件连接
on A.Id = B.CustomerId
--在连接之后的表中查询B.Id是空的情况
where B.Id is null

LC.182 查找重复的电子邮箱(简单)

LC.183 从不订购的客户(简单)


庄敬日强,功不唐捐。