一、MySQL 逻辑架构图
1. 客户端连贯管理层
负责管理客户端的连贯 / 认证 / 受权等。
2. 服务器层
负责查问解析 / 优化重写 / 查问缓存等。
3. 存储引擎层
负责数据的存储和提取。
二、数据库死锁
当事务 1 执行完第 1 个 update 时,锁定了 stockid= 4 的行,筹备去 update stockid= 3 的行;此时如果事务 2 页执行完第 1 个 update,锁定了 stockid= 3 的行
, 筹备去 update stockid= 4 的行,这样就造成了死锁的四个必要条件。资源互斥、持有并申请新资源、资源不可剥夺、循环期待。
解决办法:
突破循环期待的条件,innodb 为例,回滚持有行级锁起码记录的事务 。使得某一个或局部事务回滚,开释行级锁,其余事务就能获取到被占有的行级锁,达到解决死锁的目标。
因为死锁无奈防止,因而利用程序设计时必须思考死锁产生后的解决逻辑。最简略的方法是从新执行被数据库存储引擎回滚的那个事务即可。
三、多版本并发管制(MVCC)
MVCC 能够认为是行级锁的一个变种,然而它在很多状况下防止了加锁操作,因而开销更低。MVCC 没有一个对立的规范,各个数据库如 Mysql,Oracle,PostgreSQL 等都有本人的实现形式。尽管实现机制不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行。
实现原理:
通过保留数据在某个工夫点的快照,使得每个事物看到的数据都是统一的。后面说到不同的数据库实现原理不同,典型的有乐观锁和乐观锁。上面以 innodb 的简化版行为来阐明 MVCC 是如何工作的。
InnoDB 的 MVCC,是通过在表的每行记录前面保留两个暗藏的列来实现的。这两个列的值,别离保留行的创立工夫和过期工夫(即删除工夫)。然而,它们存的并不是实在工夫戳,而是零碎版本号。每开始一个新的事务,这个零碎版本号都会主动递增。事务开始时的零碎版本号会作为事务版本号,用来和查问到的每行记录的版本号做比拟。上面看一下在 REPEATABLE READ 的隔离级别下,MVCC 具体是怎么工作的。
1.SELECT 操作
a.InnoDB 只查找版本号小于或等于以后事务版本号的数据行,这样能够确保事务读取到的行,要么是事务开始前就存在的,或者是这个事务自身插入或批改的。
b. 行的删除版本号要么未定义,要么大于以后事务版本号,这样能够确保事务读取到的行,在事务开始前没有被删除。
只有合乎 a,b 两个条件的记录行才会被查问到。
2.INSERT 操作
InnoDB 为新插入的每一行保留以后零碎版本号作为行创立版本号。
3.DELETE 操作
InnoDB 为删除的每一行保留以后零碎版本号作为行删除版本号。
4.UPDATE 操作
InnoDB 为插入一行新记录,保留以后零碎版本号作为新创建行的创立版本号;同时以后零碎版本号作为原来行的行删除版本号。
留神,MVCC 只在可反复读和读已提交的隔离级别下工作。因为读未提交总是会读取最新的数据,而不是合乎以后事务版本号要求的数据。而串行化会为所有的读操作加锁。