InnoDB锁
MyISAM和InnoDB存储引擎使⽤的锁:
- MyISAM采⽤表级锁(table-level locking)。
- InnoDB⽀持⾏级锁(row-level locking)和表级锁,默认为⾏级锁
- 表级锁: MySQL中锁定 粒度最⼤ 的⼀种锁,对当前操作的整张表加锁,实现简单,资源消耗也⽐j较少,加锁快,不会出现死锁。其锁定粒度最⼤,触发锁冲突的概率最⾼,并发度最低,MyISAM和 InnoDB引擎都⽀持表级锁。
- ⾏级锁: MySQL中锁定 粒度最⼩ 的⼀种锁,只针对当前操作的⾏进⾏加锁。 ⾏级锁能⼤⼤减少数据库操作的冲突。其加锁粒度最⼩,并发度⾼,但加锁的开销也最⼤,加锁慢,会出现死锁
InnoDB锁类型
实现了两种标准的行级锁
- 共享锁(S Lock):允许事务读一行数据
- 排他锁(X Lock):允许事务删除或更新一行数据
S 锁仅与 S 锁兼容
一致性非锁定读
InnoDB 存储引擎通过多版本控制的方式来读取当前执行时间数据库中的行数据。如果读取的行正在执行 DLETE 或 UPDARA 操作,这时读操作不会因此去等待行上锁的释放,相反InnoDB存储引擎会去读取行的一个快照数据。
一个行记录可能不止一个快照数据(通过undo 段来实现),一般称这种技术为行多版本技术,由此带来的并发技术称为多版本并发控制(MVCC)。
事务隔离级别中
READ-COMMITTED(读取已提交),REPEATABLE-READ(可重复读)下,使用一致性非锁定读。然而他们对于快照数据的定义却不同
READ-COMMITTED(读取已提交):总是读取锁定行的最新一份的快照数据。
REPEATABLE-READ(可重复读):对于快照数据,总是读取事务开始时的行数据版本

一致性锁定读
用户想要显式地对数据库的 SELECT 操作进行加锁以保证数据逻辑的一致性。

行锁的三种算法
- Record Lock:单个行记录上的锁
- Gap Lock:间隙锁,锁定一个范围,但不包含记录本身
- Next-Key Lock:Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身
锁问题/并发事务带来的问题
通过锁机制可以实现事务的隔离要求,使得事务可以并发的工作。锁提高了并发,但是却会带来潜在的问题。不过好在事务隔离性的要求,锁只会带来三种问题
- 脏读(Dirty read): 当⼀个事务正在访问数据并且对数据进⾏了修改,⽽这种修改还没有提交到数据库中,这时另外⼀个事务也访问了这个数据,然后使⽤了这个数据。因为这个数据是还没有提交的数据,那么另外⼀个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。
READ-UNCOMMITTED(读取未提交)
- 丢失修改(Lost to modify): 简单来说就是一个事务的更新操作会被另一个事务的更新操作所覆盖,从而导致数据不一致。例如
1)事务1将行记录r 更新为v1。但是事务1并未提交
2)与此同时,事务2将行记录r 更新为 v2,事务2未提交
3)事务1提交
4)事务2提交
但是在当前数据库的任何隔离级别下,都不会导致数据库理论意义上的丢失更新问题,这是因为,对于行的DML操作,需要对行或更粗粒度的对象加锁,因此上述中,事务2不能对行记录r 进行更新操作,其会被阻塞,直到事务1提交、
我们遇到的一般是逻辑意义上的丢失更新问题
1)指在⼀个事务T1查询⼀个数据,放入本地内存,并显示给一个终端用户user1
2)另外⼀个事务T2也查询了该数据,放入本地内存,并显示给一个终端用户user2
3)user1修改了这个数据后,更新数据库并提交
4)user2修改了这个数据后,更新数据库并提交
这样user1的修改结果就被丢失。
例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。
解决方法:就是让事务在这种情况下的操作变成串行化,而不是并行操作。即在步骤1)中,对用户读取的记录加上一个排他 X 锁。同样步骤2)中,用户同样需要加一个排他 X锁。这样user2就必须等
- 不可重复读(Unrepeatableread): 指在⼀个事务内多次读同⼀数据集合。在这个事务还没有结束时,另⼀个事务也访问该同⼀数据集合,并做了一些DML操作。因此,在第⼀个事务中的两次读数据之间,由于第⼆个事务的修改导致第⼀个事务两次读取的数据可能不太⼀样。这就发⽣了在⼀个事务内两次读到的数据是不⼀样的情况,因此称为不可重复读。
不可重复读,是因为在读取已提交的隔离级别下,读取的是该记录的最新的快照。
一般来说不可重复读是可以接受的,因为其读到的是已经提交的数据,本身并不会带来很大的问题,因此很多厂商将其数据库的默认隔离级别设置为 READ-COMMITTED(读取已提交)
InnoDB 存储引擎的默认⽀持的隔离级别是 REPEATABLE-READ(可重读)
解决方案:通过Next-Key Lock 算法来避免不可重复读的问题
脏读和不可重复读的区别是:脏读是读到未提交的数据,而不可重复读读到的却是已经提交的数据,但是其实违反了数据库事务一致性的要求

1412

被折叠的 条评论
为什么被折叠?



