事务串行化执行是OK的,但效率低。而事务之间有一些可以并发的操作:
并发执行会打破事务的隔离性,根据破坏的程度分成可重复读、读已提交、读未提交等隔离级别,每种级别都决定了多线程并发时数据可见性不同,是并发和隔离性之间的权衡,也因此产生了幻读、不可重复读、脏读等问题。
将串行执行的调度序列中的一些无冲突的操作进行调整,不影响最终结果,但能够增加事务间并发程度,称为冲突等价和可串行化调度序列。如果能证明某个并发控制方案能让并发事务都生成冲突可串行化的 schedule,则说明该并发控制方案达到了可串行化隔离级别。
但,两个不满足冲突等价关系的 schedule序列也可能产生相同的执行结果,也就是说它们等价。
# 查看隔离级别
show variables like 'transaction%'
# 设置隔离级别
set global transaction isolation level read uncommitted;
# 关闭默认自动提交
set autocommit = 0;
事务1执行修改记录,事务2能够读到,如果事务1回滚,则事务2就是脏读。
读不加锁,写加写锁。
事务1先开始,select后,事务2执行update,此时相互不影响。事务2提交后,事务1才能够看到事务2的更新,导致不可重复读、幻读现象。
每次select都会生成一个read view,可能后续select生成的read view和第一次select时不一样,读是当前读,写加写锁。
现象:事务前后两次读结果一样,没有看到其它事务的更新、插入、删除。但是可以修改其它事务删除或者插入的数据,导致幻读现象。
第一次select时会生成read view,只能看到当时已提交的最大事务版本,不能看到活跃事务的数据,读是快照读,写加写锁,next-key来防止插入新记录。
实现冲突可串行化的方法有基于锁的方式和基于乐观的方式两种。
锁只是一个手段和工具。对锁如何使用是更为关键的,也就是对锁的使用协议的不同,决定了能否达成该目标。需要慎重考虑锁的种类、加锁和解锁的时机、锁的粒度、锁的相容性等。
主要有两种:
二阶段锁能够保证冲突可串行化,但是不能避免死锁和级联回滚问题。因此有两个变种:
Innodb检测到死锁后会回滚。
死锁就是多个事务按照相反的顺序加锁,持有一部分资源并等待对方的资源,造成的一个互相阻塞的情况。解决办法通常是死锁检测和解除。
Innodb会检测循环依赖并立刻返回错误,回滚掉持有行级锁最少的事务,或者等待死锁超时。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。