innodb 引擎锁相关

1.innodb 引擎


a.innodb用锁机制实现acid(原子,一致,隔离,持久)事务,但为了提高并发性,也用了mvcc处理。
innodb中只有隔离级别为可重复读或提交读才适用mvcc,以下的说明默认是在可重复读级别下。


b.innodb的读取分为当前读与快照读
(1)当前读,即加共享锁读。
有以下场景时使用:
lock in share mode;结尾
for update;结尾
更新语句(增删改)
这里需要说明一下,更新语句本身也带有查询,这个查询是隐式的。MySQL Server根据条件发出筛选查询,
InnoDB引擎将第一条记录返回,并加锁。MySQL Server起一个Update请求更新,一条记录完成,再操作下一条。
(2)快照读,不加锁读,通过MVCC实现。


c.mvcc多版本并发控制。
简单理解,mvcc就是保存了每条数据的每个版本(从出生到删除)。
(1)mvcc在每条数据加入两个字段,分别为插入版本和删除版本。每开启一个事务,系统会为事务
分配一个自增的版本号。
插入时,数据的插入版本=事务版本。
修改时,原数据不动,增加一条更改后数据,原数据删除版本=事务版本,更改后数据插入版本=事务版本。
删除时,删除版本=事务版本。
(2)事务读取数据,返回数据必须满足:
(a)插入版本必须小于等于事务版本,确保读取的行都是事务之前已经存在的,或者是由当前事务创建或修改的行。
(b)删除版本未定义或大于当前事务的版本号,确定了当前事务开始之前,行没有被删除。
mvcc无法完全隔绝幻读。


d.mvcc与乐观锁。
mvcc的处理方法与乐观锁有点类似,但处理的问题不一样。
MVCC用来解决读-写冲突,在读操作不用阻塞写操作,避免了脏读和不可重复读。
乐观锁通常指用来解决写-写冲突的无锁并发控制,先修改数据,提交数据时加上条件(数据版本=事务版本),
返回的处理函数等于1则成功(假设只改一条数据),0则失败,表示其他事务已经改过记录了。
innodb用MVCC用来解决读-写冲突,写-写冲突是悲观锁的方式,修改数据使用排他锁独占数据来保证隔离性。


e.疑问。
mvcc的实现,假设事务a先开始,事务b(版本比a高)后开始,事务b查询数据,然后a修改提交数据,根据读取
原则,b应该读到提交后数据(不可重复读),而事实上不会发生。


2.Java事务与mysql事务
关注这个问题的根源是为弄清楚事务与多后端系统是否冲突。以下基于目前认知,还有待考究和认证。
首先,纠正以前的错误看法,JDBC事务与Java没有关系,其实是mysql的实现,这就是为什么事务需要数据库引擎
的支持,以及隔离级别由数据库实现。
JDBC事务应该是隐式地跑start transaction;commit;rollback;这些语句。
似乎在自动提交模式下,JDBC会对每一个语句前后都加上start transaction;commit;
除了JDBC事务,还有一个重要概念是ORM事务,ORM框架有一个重要概念是Session,Session会缓存数据,
只有在flush或者commit时才同步数据,这对没有事务的数据库系统也有意义。
网上说hibernate只做了数据的缓存,没有自己的事务实现,所以底层还是使用了mysql事务?只是sql的提交
不实时?如果只是这样,那么多后端系统使用hibernate其实是安全的?
网上对此大部分意见是不要在多系统中部署hibernate,原因也很直接,不同的hibernate之间的缓存是不透明的。
Mybatis的事务实现了两种方式,Jdbc和Manage,如果使用JDBC方式,可以比较稳地保证事务符合acid。
每个独立事务,包括其上下文,都在一个Connection里面执行。

 

2019.01.19

posted @ 2019-07-12 00:41  枫林晚月  阅读(138)  评论(0编辑  收藏  举报