并发带来的问题,通常采用加锁就可以解决,我们尝试一下用锁来解决一下试试:
1 读未提交(READ UNCOMMITED)解决丢失修改
丢失修改是因为事务A修改数据的时候,其它事务也可以修改,只要保证某事务修改数据过程中,其它事务不能修改就可以了,但是可以读取,所以脏读解决不了。
为了解决丢失修改的写覆盖问题,未提交读的实现原理:
1.事务对当前被读取的数据不加锁
2.事务对当前更新的数据加排他锁,直到事务结束才释放
说明:第二条保证了事务A修改数据,其它事务不能修改数据;但是第一条读取数据由于不加锁,会产生脏读。
2>读提交(READ COMMITED)解决脏读
脏读是因为事务A读取到了别的事务修改但没有提交的数据。只要事务修改的数据,没有提交之前不被其他事务读物到就可以避免脏读。
读提交的实现原理:
1.事务对当前被读取的数据加共享锁,读取之后就释放锁
2.事务对当前更新的数据加排他锁,直到事务结束才释放
说明:更新数据的时候加了排他锁,读取的数据的时候加了共享锁,保证了其它事务提交之前,读取不到它们修改过的数据。
2>可重复读(REPEATABLE READ)解决不可重复读
不可重复读是因为事务在两次相同查询的中间过程,别的事务执行并提交修改操作。使得两次读取的结果内容不一致。
可重复读实现原理:
1.事务对当前被读取的数据加共享锁,直到事务结束才释放
2.事务对当前更新的数据加排他锁,直到事务结束才释放
说明:第一条保证了事务在读取数据过程中,别的事务不允许修改。但是解决不了幻读的问题。
2>串行化(SERIALIZE)解决幻读
幻读因为事务在两次相同查询的中间过程,别的事务执行并提交了新增或者删除操作。使得两次读取的数据行数不一致。
串行化实现原理:
1.事务对当前被读取的数据加表共享锁,直到事务结束才释放
2.事务对当前更新的数据加表排他锁,直到事务结束才释放
说明:通过在一次操作中对整张表进行加锁,从而其他事务对整张表能insert、delete、update,所以不会有行记录的增加或减少,从而保证了当前事务两次读之间数据的一致性,解决了幻读问题。
由于通过加锁的方式,容易导致读写阻塞,并发性能很差,所以innodb采用了MVCC机制。
MVCC(Mutil-Version Concurrency Control),就是多版本并发控制。在Mysql的InnoDB引擎中就是指在已提交读(READ COMMITTD)和可重复读(REPEATABLE READ)这两种隔离级别下的事务对于SELECT操作会访问版本链中的记录的过程。这就使得别的事务可以修改这条记录,反正每次修改都会在版本链中记录。SELECT可以去版本链中拿记录,这就实现了读-写,写-读的并发执行,提升了系统的性能。