并发控制

并发控制

一、常见的并发问题

​ 更新丢失:两个或多个事务同时更新一条记录,会发生更新丢失。导致更新结果不可控。可以分为回滚覆盖和提交覆盖。

​ 回滚覆盖:一个事务回滚操作,把其他事务已提交的数据覆盖了

​ 提交覆盖:一个事务提交操作,把其他事务已提交的数据覆盖了

​ 脏读:一个事务读取到了另一个事务修改但未提交的数据。

​ 不可重复读:一个事务中多次读取同一行记录,后面读取的和前面读取的不一致。

​ 幻读:一个事务中多次按相同条件查询,结果不一致。

二、锁分类

1.按粒度分

​ 表级锁:每次操作锁住整张表,粒度最大

​ 行级锁:每次操作锁住一行数据,粒度最小,仅Innodb引擎支持

​ 页等锁:每次锁定相邻的一组记录,粒度在表锁和行锁使用,仅BDB引擎支持

2.操作类型

​ 共享锁(读锁/S锁):对同一份数据,多个读操作可以同时进行。事务A对记录加了S锁,就可以对记录进行读操作,不能修改。其他事务也可以对记录追加S锁,但不能追加X锁。

​ 排它锁(写锁/X锁):当前写操作没有完成前,会阻断对其他事务获取该数据项上的写锁和读锁。事务A对记录添加了X锁,就可以对该记录读和写,其他事务不能对该记录进行读写。

意向锁

​ S、X锁都是表级锁。意向锁是表级锁。当对表中记录加S或X锁之前,会先对表加IS或IX锁。主要用于迅速判断能否加锁。 一个记录被显式加锁前,它的所有父级记录都要加上意向锁(例:给表中某行显式加锁,那这个表和这个表所在的数据库都要加意向锁)。这样一个事务就不必遍历整个文件树来判定它能否给一个记录加锁。

​ 意向共享锁(IS):如果一个记录被加上了IS锁,它的子记录只能加S锁。

​ 意向排它锁(IX):如果一个记录被加上了IX锁,表明它的走子记录可以加S锁或X锁。

3.操作性能

​ 乐观锁:一般实现方式是对记录数据版本进行比对,在数据更新提交时才会进行冲突检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。并发度很高

        乐观锁的实现:使用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。何谓数据版本?即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的 “version” 字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据。

​ 悲观锁:对一条数据修改的时候,为了避免同时被其他人修改,修改之前先锁定该记录,再修改。共享锁和排它锁都属于排他锁。

三、死锁