首页 > 数据库 >数据库基础——锁与事务

数据库基础——锁与事务

时间:2022-10-17 18:33:05浏览次数:56  
标签:事务 快照 记录 数据库 基础 索引 意向锁 select

  一、锁(MyISAM 和 InnoDB)

  1. MyISAM: 默认表级锁,不支持行锁。

    select  读锁为共享锁。可以同时执行多个读的操作

    update、insert、delete 等操作为写锁,写锁是排他锁。 

    手动加锁: lock tables table_name read/write;

    为select 添加排他锁: select ..................................   for update;

  2. Innodb 默认行级锁,也支持表级锁。

  表级锁:

  • 表读写锁

    读为共享锁,写为排他锁。 加表锁可以使用 lock tables/table table_name read/write;

    命令show open tables,可以查看对应表锁的个数。

  • 意向锁

    这是InnoDB引擎实现的表级锁,是为了全表更新数据时或者加其他表锁时性能提升,避免全表遍历排查某行数据是否加了行锁,对加了行锁的表,加上意向锁标识;

    意向锁分为意向共享锁(IS锁)和意向排他锁(IX锁),意向锁之间不互相排斥,只是作为表锁的标识,如表中多行记录可以既有共享锁和排他锁,那么导致表的意向锁就会既有IS锁和IX锁,这种意向锁就是为了给表加锁时可以更快的判断能加哪种锁。

  • 自增锁

    自增锁是一种特殊的表级别锁。它是专门针对AUTO_INCREMENT类型的列,对于这种列,如果表中新增数据时就会去持有自增锁。简言之,如果一个事务正在往表中插入记录,所有其他事务的插入必须等待,以便第一个事务插入的行,是连续的主键值。

  行级锁:通过给索引的索引项加锁实现的,所以只有通过索引条件检索的数据,InnoDB才能加行锁,否则会对所有行或行间隙加锁,表现为使用了表锁。根据锁定范围分为记录锁(Record Locks)、间隙锁(Gap Locks)、临键锁(Next-Key Locks)和插入意向锁(Insert Intention Locks)。按照功能仍可以分为共享锁(S)和排他锁(X)。

  innodb 会自动给insert、update、delete语句加X锁。但select不会加任何锁(非Serializable隔离等级),除非显式的加锁: select ...... lock in share mode  (S锁) | select ...... for update (X锁)

  • 记录锁

    锁定索引中一条记录。其实锁住的是索引(如果是主键索引,就锁住主键索引,如果是辅助索引,则锁住辅助索引和主键索引),如果检索记录没有用到索引,那么就会将表的所有聚簇索引记录都锁定,表现为表锁;

  • 间隙锁 (Gap)

    是一种区间锁,锁住的是索引开区间,即不包括两端,也就是不包括索引记录本身;间隙锁可以防止幻读,即在当前事务增删改中,用到间隙锁后,其他事务便无法加上间隙记录的X锁,也就不能增删改间隙记录;

  • 临键锁 (Next-Key) = 行锁  + Gap锁

    锁定索引区间为左开右闭区间的锁。在 RR和Serializable级别下,会在当前读的操作中使用临键锁。InnoDB会根据不同SQL操作对临键锁进行优化:

    当主键索引或唯一索引全部命中时临键锁会降级为记录锁,即锁住记录本身,而不是范围;

    当主键索引或唯一索引部分命中时,行锁+Cap锁

    当辅助索引等值查询且有记录时,临键锁会锁住等值记录的主键索引项和辅助索引项,同时会加间隙锁锁住辅助索引区间项

    当范围匹配时,就使用临键锁,即Record Lock + Gap Lock。

  • 插入意向锁

    是一种Gap Lock,不是意向锁,在insert操作时产生;插入意向锁不会阻止任何锁,对插入的记录进行锁定,防止其他事务插入相同主键记录,而不同主键记录之间的插入互不影响。

二、事务

  1. 数据库事务的四大特性 ACID

  • 原子性 (Atomic):事务包含的所有操作,要么全部执行,要么全部失败回滚。
  • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态指数据库中的数据应满足完整性约束。
  • 隔离性(Isolation):多个事务并发执行时,事物之间应该互不干扰。
  • 持久性(Durability):一个事务一旦提交,它对数据库的修改应该是永久的。持久性意味着当系统或者介质发生故障时,确保已提交事务的更新不能丢失,即对已提交事务的更新能恢复。一旦一个事务被提交,DBMS(数据库管理系统)必须保证提供适当的冗余,使其耐得住系统的故障。所以持久性主要在于DBMS的恢复性能。例如 innoDB会将所有的数据库修改保存在二进制日志中。

  2. 事务相关的SQL语句

  • show variables like 'transaction_isolation'/select @@transaction_isolation;     查看当前session的隔离级别
  • start transaction    开启事务
  • commit  提交
  • rollback 回滚
  • set session transaction isolation level (read uncommitted)/ (read uncommitted)/ (repeatable read )/ (serializable) 

  3. 事务隔离级别以及各级别下的并发访问问题

    3.1 事务隔离的4个级别

    (1)读未提交——read uncommitted:在事务过程中,可以读取其他事务未提交的数据。

    (2)读已提交——read committed: 在事务过程中,可以读取其他事务已提交的数据。

    (3)可重复读——repeatable read:可重复读,事务中多次读取,数据一致。

    (4)串行化——serializable:任何操作都会请求响应的锁。能否执行要看能否获取到操作行的锁。按照锁的兼容关系执行。

    3.2 常见的几种并发问题

    (1) 脏读: 事务A读取数据的过程中,能读取到其他事务修改但未提交的数据。  RC级别以上可以避免。

    (2)不可重复读: 事务A多次读取同一条数据,取得的数据结果不一致。 RR级别以上可以避免。

    (3)幻读: 当事务操作时,有其他事务插入或删除了数据,导致当前事务进行了错误操作。 serializable级别可以避免。

  4. 当前读与快照读

    对于RC和RR两种模式,在RC模式下,会读取最新的已提交数据。RR模式,会保证多次读取数据一致性,是否读取最新版本,要看建立快照的时间。

    当前读:select...lock in share mode, select ... for update, update, delete, insert。 即加锁的操作都可以视为当前读。读取的是记录的最新版本,而且保证其它并发事务不能修改当前记录。 

   为什么 update,delete, insert等操作都称为当前读呢???以update为例,原因如下图所示:

   快照读: 不加锁的非阻塞读,(非serializable级别的)select

    InnoDB下数据行里除了数据字段还有一些隐藏字段,例如DB_TRX_ID, DB_ROLL_PTR, DB_ROW_ID等,这些就是实现快照读的关键。

  •    DB_TRX_ID: 最后一次对本行做修改的事务ID,每处理一个事务,其值自动加1
  •    DATA_ROLL_PTR 指向当前记录项的rollback segment的undo log记录,找之前版本的数据就是通过这个指针
  •    DB_ROW_ID,当由innodb自动产生聚集索引时,聚集索引包括这个DB_ROW_ID的值,否则聚集索引中不包括这个值,这个用于索引当中
  •    DELETE BIT位用于标识该记录是否被删除,这里的不是真正的删除数据,而是标志出来的删除,真正意义的删除是在commit的时候

   当我们对一行数据进行修改时,innoDB会更新DB_TRX_ID 事务ID,并将更新前的行保存到undo日志中,然后DB_ROLL_PTR指向undo日志中的这一行。流程如下所示:

 初始插入行:

事务1修改:

事务2修改:

  在RR级别下,事务开始时的第一次快照读会创建一个快照Read View 将系统中其他活跃的事务记录下来,此后当再次快照读的时候,仍使用同一个Read View。 RC级别下每次快照读都重新建立快照,这就是为什么RC模式读取的是最新提交的数据。

 InnoDB在RR与Serializable级别下如何避免幻读? 临键锁!!!!临键锁会锁住记录本身和附近的区间,以防止幻读。例如A字段为int类型,且为普通索引,如下图所示。当事务1删除 A= 10的数据时,innoDB会锁定(7,10] 和(10,12]的区间。这时事务2想要插入A=9的数据,就会阻塞。

标签:事务,快照,记录,数据库,基础,索引,意向锁,select
From: https://www.cnblogs.com/lostO/p/16797084.html

相关文章

  • 6_面向对象基础
    1.面向对象和面向过程面向过程重点在于:步骤面向对象重点在于:对象一般大型项目都采用面向对象编程思维2.面向对象三大特性object:所有类的父类,超类,上帝类,......
  • Rust编程基础
    Rust是一门系统编程语言,专注于安全,尤其是并发安全,支持函数式和命令式以及泛型等编程范式的多范式语言。Rust在语法上和C++类似,但是设计者想要在保证性能的同时提供更好的内......
  • JavaWeb(一):MySql基础
    目录​​1、数据库相关概念​​​​1.1数据库​​​​1.2数据库管理系统​​​​1.3常见的数据库管理系统​​​​1.4SQL​​​​2、MySQL​​​​2.1MySQL安装​​​......
  • python基础之生成器
    异常处理语法结构异常处理实战应用生成器对象生成器对象实现range方法生成器表达式生成器笔试题模块简介今日内容详细异常常见类型SyntanxError语法错误Nam......
  • 进入python的世界_day16_python基础——异常捕获的处理、生成器对象、生成器表达式
    一、异常捕获1.错误类型语法错误>>>syntaxerror名字错误>>>namerror索引错误>>>Indexerror缩进错误>>>indentationerror等等......2.异常处理语法结构1.语法结......
  • 数据库连接池-概述、实现介绍
    数据库连接池-概述概念:其实就是一个容器,存放数据库连接的容器。当系统初始化后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完......
  • Linux下更改MySQL数据库存储路径
    1、home目录下建立data目录,data目录下建立mysql目录  2、首先停止掉mysql服务,在终端中执行"/etc/init.d/mysqlstop"或者执行"servicemysqldstop"并回车确定。3......
  • C语言零基础入门—函数-习题
    C语言零基础入门—函数-习题本节课的任务是:完成5道习题。下边的题目,都需要使用函数的知识来求解(也就是编写自定义函数求解)01-二元一次函数求解求方程​​ax^2+bx+c=......
  • python基础之异常处理、生成器对象、生成器表达式
    A-Z65-90a-z97-122迭代取值=for循环取值(每次取值都依赖于上一次取值)python基础之异常处理、生成器对象、生成器表达式目录一、异常处理语法结构1.异常的常见类型2......
  • ORACLE如何使用DBLINK连接另一个数据库(两数据库关联操作)
    一、实现结果:在当前数据库去访问另一个数据库某用户下的视图二、创建DBLINK方法:CREATEPUBLICDATABASELINKDBLINKCONNECTTOTOTALPLANTIDENTIFIEDBYTOTALPLANTUSI......