mysql 怎么保证acid特性的

原子性A:事务要么都做(提交),要么都不做(回滚);事务是访问并更新数据库各种数据项的一个程序执行单元,是不可分割的工作单位,当回滚时,回访事务具体操作的逆运算

隔离性 I: 事务的隔离性要求每个读写事务的对象对其他事务的操作对象能相互分离,也就是事务提交前对其他事务都不可见,通过MVCC(主要用于读)锁(主要用于写)来实现。 MVCC时多版本并发控制,主要解决一致性非锁定读,通过记录和获取行版本,而不是使用锁来限制读操作,从而实高效并发读性能。

锁用来处理并发DML(写)操作。 数据库种提供粒度锁的策略,针对(聚集索引B+树)、页(聚集索引B+树叶子节点)、行(叶子节点种的某一段记录行)三种粒度加锁。

持久性 D:

事务提交后,事务DML(写)操作将会持久化(写入redolog磁盘文件,哪一个页,页偏移值,具体数据);即机器突然宕机,数据库也能恢复数据,redolog记录的是物理日志

一致性C:

事务将数据库从一种状态转变为下一种一致性的状态,在事务执行前后,数据库完整性约束没有被破坏,例如:一个表的姓名是唯一的键,如果一个事务对姓名进行修改,但是在事务提交或事务回滚后,

表中的姓名变得不唯一了,这样就破坏了一致性,一致性由原子性、隔离性以及持久性共同维护。

 

 

 

 

innodb:

索引

1、主键索引:非空唯一索引,一个表只有一个主键索引,在innodb中,主键索引的B+树包含表数据信息, PRIMARY KEY(key)

2、唯一索引:不可以出现相同的值,可以有NULL值, UNIQUE(key)

3、普通索引:允许出现相同的索引内容,  INDEX(key)

4、组合索引:对表上的多个列进行索引  INDEX idx(key1,key2,[,.....]);       UNIQUE(key1,key2,[,.....]);      PRIMARY KEY(key1,key2,[,.....]);

5、全文索引:基于倒排索引

 

 

innnodb引擎 行级锁,innodb中表是索引组织表,每张表有且只有一个主键

主键的选择:

1、如果显示设置PRIMARY KEY,则表示该key为表的主键

2、如果没有显示设置,则从非空唯一索引中选择

      a、只有一个非空唯一索引,则选择该索引为主键

       b、有多个非空唯一索引,则选择声明的第一个为主键

3、没有非空唯一索引,则自动生成6个字节的_rowid作为主键

 

innodb 并发锁:

事务 & mysql INNODB的隔离级别以及 脏读幻读_主键

 

 

 

 

 

 

更改事务隔离级别:  SET SESSION TRANSACTION ISOLATION LEVEL  XXX

读未提交 : READ UNCOMMITTED

读已提交: READ COMMITTED。 使用MVCC策略

可重复读: REPEATABLE READ。 使用MVCC策略

 

 


 

MVCC策略:

多版本控制,解决  一致性非锁定读

当一个事务锁定某行数据,其他事务修改提交(commit)这行,会产生一个快照数据,并且需要按照一定规则来读取快照数据(不同的隔离级别不同):

 

 读已提交(commit)状态:

a\比如事务A读,事务B写不提交,则事务A再读,两次读的东西一致,解决了脏读问题(解决脏读

b\  会读取最新的快照数据,比如事务A读,事务B写并提交,则事务A再读,两次读的东西会不一致

 

事务 & mysql INNODB的隔离级别以及 脏读幻读_数据库_02

 

 可重复读隔离级别 :读取所有事务开始之前的数据,比如事务A读,事务B写并提交,则事务A再读,两次读的东西一致

但是这会引入幻读问题(如果没加锁):比如事务A读,事务B写并提交,则事务A再读,两次读的东西一致,A再重复写刚刚B写(比如插入一条数据)的内容,会说已经存在

事务 & mysql INNODB的隔离级别以及 脏读幻读_主键_03

 

 

解决幻读:

如果可重复读,在事务A读的时候加锁了 ,事务B就会修改失败

事务 & mysql INNODB的隔离级别以及 脏读幻读_主键_04

也可以加写锁

 

 

 

 

 


 

 

 

 

B+树组织结构:

事务 & mysql INNODB的隔离级别以及 脏读幻读_结点_05

 

 

 

 

B+树类别

1、基于聚集索引, 叶子节点存储的是行数据

2、基于辅助索引,叶子节点存储的是 索引+ 主键key   ;通过辅助索引找到主键索引,再找到具体的行


 

【这里MyISAM和InnoDB有区别】

MyISAM更是索引和文件分离,B+树的叶子结点的数据域存放的是文件内容的地址,主索引和辅助索引的B+树都是如此,那么如果我改变了一个地址,是不是所有的索引树都得改变,正如前面我们讲的在磁盘上频繁的读写操作是效率很低的,而这块又不适用局部原理,因为逻辑上相邻的结点,物理上不一定相邻,那么这样就会造成效率上的降低

InnoDB就产生了,它让除了主索引以外的辅助索引的叶子结点的数据域都保存主键,先通过辅助索引找到主键,然后通过主键找到叶子结点的所有数据,听起来貌似很麻烦,遍历了两棵树,但是,这样如果有了修改的话,改变的只是主索引,其它辅助缩印都不用动,而且,数据库中的树的每一个结点的key可不是咱们给的那么少,试想如果一个结点有1024个key,那么高度为2的B+树都有1024*1024个key,所以一般树的高度都很低,所以,遍历树的消耗几乎忽略不计 

————————————————
版权声明:本文为CSDN博主「John__xs」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/bitboss/article/details/53219945


 

 

mysql指令:

显示开启事务 START TRANSACTION | BEGIN

提交事务,并使得已对数据库做的所有修改持久化: COMMIT

回滚事务,结束用户的事务,并撤销正在进行的所有未提交的修改 : ROLLBACK

创建一个保存点,一个事务可以有多个保存点: SAVEROINT  identifier

删除一个保存点: RELEASE SAVEPOINT identifier

事务回滚到保存点 : ROLLBACK TO [ SAVEPOINT] identifier