简单了解MySQL

1. MySQL逻辑架构

简单了解MySQL_第1张图片

  1. 第一层:连接以及线程处理,该层主要是处理客户端的连接,以及为每一个客户端连接分配一个线程,每个连接中的查询语句只会在自己的线程中执行,MySQL会管理一个线程池,该线程池中缓存着所有线程。
  2. 第二层:MySQL中的核心功能服务(跨数据库存储引擎的)基本都在这一层。查询缓存就是用来缓存查询语句执行结果的,如果某一个SQL语句的查询结果已经在查询缓存中,那么就直接返回缓存中的数据(就是相当于HashMap,以SQL语句为键,查询结果集为值),而一旦表结构或者表数据(增删改)发生了改变,那么缓存中的数据会立刻失效,所以该功能适合大量查询的表结构,而不能用于经常做数据修改的表,该功能可以选择是否启用;分析器和优化器就是用来解析SQL语句,然后进行优化的。
  3. 第三层:数据库存储引擎,负责对数据库中数据的存储与提取。

2. 并发控制

    1. 在多线程操作同一个共享资源时,一定会发生并发问题,MySQL采用了读写锁来保证在多线程情况下的数据读写并发安全问题。

    2. 读写锁:对于读写锁,只需要记住一点,那就是读锁是共享锁,多个线程都可以持有,而写锁是独占锁,只能有一个线程持有。写锁与读锁,写锁与写锁不能同时存在。读锁就保证了可以有多个线程同时读取数据库数据,但也禁止了某个线程持有写锁,也就是进行写数据操作;而对于写锁,只能有一个线程持有进行数据库写操作,而其他的写锁或读锁都不能存在。

    3. 锁粒度:为了提高共享资源的并发性,我们可以尽量缩小锁定的共享资源范围,也就是减小锁粒度,这样就可以大大提高资源的并发性,提高读写性能。但是频繁的加锁与解锁也会消耗性能资源。MySQL有两种锁策略,一种是表级锁,另一种是行级锁。表级锁就是锁住操作的整张数据表,而行级锁则是锁住被操做的某行数据,行级锁只在存储引擎中实现,服务层(逻辑架构第二层)则实现了表级锁。

3. 事务

    1. 事务的三个属性ACID:原子性、一致性、隔离性、持久性。

(1)原子性:指的是事务中的一组SQL语句操作要么全部执行成功,要么全部执行失败。

(2)一致性:事务的执行结果必须保证数据库数据库是从一个一致性状态转移到另一个一致性状态。

(3)隔离性:事务与事务之间在未提交之前是不可见的,事务中所执行的SQL操作无法感知到另一个事务中所执行的SQL操作。

(4)持久性:事务一旦执行提交,那么所有的数据都将永久保存到数据库中。

    2. 事务与锁一样,同样会带来性能开销,所以需要依据系统业务,来判断是否需要实现事务管理能力的数据库存储引擎。

    3. 事务隔离级别:事务具有隔离性,但隔离性同样也需要分级,包括如下级别

(1)read uncommitted(未提交读):最低隔离级别,即使当前事务没有提交数据修改操作,但修改的数据在其他事务中也是可见。这种情况就会导致数据脏读的情况(当前事务读取到其他事务未提交的数据),基本不用该级别。

(2)read committed(提交读):比未提交读级别高,当前事务只能读取到其他已经提交的事务所做的修改,换句话说也就是一个事务直到提交之前,其所执行的数据操作结果对其它事务都是不可见的。避免了脏读的问题,但是也带来了另一个问题,就是不可重复读。不可重复读指的是在一个事务中多次执行同一个查询语句得到的查询结果不是一致的。

(3)repeatable read(可重复读):比提交读的级别高,不仅保证了提交读,还避免了不可重复读问题,即事务中多次执行同一个查询语句得到的查询结果是一致的,这是MySQL的默认隔离级别。但是又会出现数据幻读的问题,所谓幻读是指同一个事务内多次查询返回的结果集不一样(比如增加了或者减少了行记录)。其实和不可重复读一样,发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据。不同在于不可重复读是同一个记录的数据内容被修改了,幻读是数据行记录变多了或者少了,用一个例子来解释什么是幻读

例子:在事务1中,查询User表id为1的是用户否存在,如果不存在则插入一条id为1的数据。

select * from User where id = 1;  

在事务1查询结束后,事务2往User表中插入了一条id为1的数据。

insert into `User`(`id`, `name`) values (1, 'Joonwhee');  

此时,由于事务1查询到id为1的用户不存在,因此插入1条id为1的数据。

insert into ` User`(`id`, `name`) values (1, 'Chillax');  

但是由于事务2已经插入了1条id为1的数据,因此此时会报主键冲突,对于事务1 的业务来说是执行失败的,这里事务1 就是发生了幻读,因为事务1读取的数据状态并不能支持他的下一步的业务。

(4)serializable(串行化):最高隔离级别,将所有的事务进行串行执行,避免了幻读以及其他问题,但也导致了非常严重的性能问题。该隔离级别会对操作的每一行数据进行加锁处理,以此保证串行执行。

    4. 数据库中的死锁:数据库指的是两个或多个事务互相占用锁定对方所请求的资源,从而导致双方都无法获取锁也都无法释放已持有锁,从而导致的死锁问题,示例如下:

//事务A中执行
update user set name = '' where id = 1;
update user set name = '' where id = 2;

//事务B执行
update user set name = '' where id = 2;
update user set name = '' where id = 1;

加入两个事务都恰好执行完第一个update语句,那么此时就分别获取了两个数据行的行级锁,而执行到下一条update语句时,发现请求的锁都被对方占有且没有释放,此时就会导致死锁问题。innoDB存储引擎对死锁情况的处理是将持有最少行级锁的事务进行回滚。

转载于:https://my.oschina.net/ProgramerLife/blog/3084847

你可能感兴趣的:(数据库)