ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

事务和锁

2022-07-22 17:01:49  阅读:95  来源: 互联网

标签:语句 事务 隔离 死锁 提交 级别


一、事务

ACID原则

即Atomicity(原子性) Consistency(一致性), Isolation(隔离性), Durability(持久性)

原子性:要执行的事务是一个独立的操作单元,要么全部执行,要么全部不执行

一致性:事务的一致性是指事务的执行不能破坏数据库的一致性,一致性也称为完整性。一个事务在执行后,数据库必须从一个一致性状态转变为另一个一致性状态。

隔离性:多个事务并发执行时,一个事务的执行不应影响其他事务的执行,SQL92规范中对隔离性定义了不同的隔离级别:

持久性:事务对数据库的修改是持久存在。

 

事务隔离级别

sql隔离标准:

READ UNCOMMITTED(读未提交)

在该级别中,事务中的修改即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据称之为脏读(Diryt Read)。这个级别会导致很多问题,性能也不会比其他级别好太多,但却缺乏其他级别的很多好处,除非真的有非常必要的理由,在实际应用中一般很少使用。

READ COMMITED(读已提交)

大多数数据库系统的默认隔离级别都是该级别(但MySQL不是)。该级别满足隔离性的简单定义:一个事务开始时,只能“看见”已经提交的事务所做的修改。也就是说,一个事务从开始直到提交前,所做的修改对其他事务都是不可见的。这个级别有时候也叫作不可重复读,因为*两次执行同样的查询,可能会得到不一样的结果。

REPEATABLE READ(可重复读)

该级别是MySQL的默认事务隔离级别,解决了脏读的问题,并保证了在同一个事务中多次读取同样的记录的结果是一致的。理论上可重复读还是无法解决另外一个幻读的问题。幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,之前的事务再次读取该范围的记录时,会产生幻行。InnoDB存储引擎通过多版本并发控制(MVCC)解决了该问题。

SERIALIZABLE(可串行化)

该级别是最高的隔离级别,它通过强制事务串行执行,避免了前面所说的幻读问题。简单来说,该级别会对读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用问题。实际应用中也很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。

注意:mysql第三四级别(REPEATABLE READ(可重复读)、SERIALIZABLE(可串行化)已经解决了幻读问题

设置事务隔离级别:

set session transaction isolation level read uncommitted;

 

事务开启

mysql执行SQL语句会被默认开启事务,插入SQL语句,再提交事务。

也可以手动开启:

1.START TRANSACTION 或 BEGIN 开始新的事务 COMMIT 提交当前事务 ROLLBACK 回滚当前事务

2.SET autocommit = 0;默认情况下 autocommit = 1,是自动提交事务的。autommit 是 session 级别的,就是当前连接更改了 autocommit,对其他连接没有影响。设置 autocommit 之后,本次连接的所有 sql 都是事务的形式,比如每次 commit 提交。

开启手动提交后,会出现隐式提交事务:

 

保存点

如果你开启了一个事务,并且已经敲了很多语句,忽然发现上一条语句有点问题,你只好使用ROLLBACK语句来让数据库状态恢复到事务执行之前的样子,然后一切从头再来,总有一种一夜回到解放前的感觉。

MYSQL提出了一个保存点(英文:savepoint)的概念,就是在事务对应的数据库语句中打几个点,我们在调用ROLLBACK语句时可以指定会滚到哪个点,而不是回到最初的原点。

定义保存点的语法如下:

SAVEPOINT 保存点名称;

当我们想回滚到某个保存点时,可以使用下边这个语句(下边语句中的单词WORK和SAVEPOINT是可有可无的)

ROLLBACK [WORK] TO [SAVEPOINT] 保存点名称;

不过如果ROLLBACK语句后边不跟随保存点名称的话,会直接回滚到事务执行之前的状态。

如果我们想删除某个保存点,可以使用这个语句:

RELEASE SAVEPOINT 保存点名称;

 

二、锁

锁分类

从锁的粒度,我们可以分成两大类:
表锁 :开销小,加锁快;不会出现死锁;锁定力度大,发生锁冲突概率高,并发度最低
行锁:开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高

不同的存储引擎支持的锁粒度是不一样的:InnoDB行锁和表锁都支持MyISAM只支持表锁!InnoDB只有通过索引条件检索数据才使用行级锁,否则,InnoDB使用表锁也就是说,

 

表锁其实我们程序员是很少关心它的:

  • 在MyISAM存储引擎中,当执行SQL语句的时候是自动加的。
  • 在InnoDB存储引擎中,如果没有使用索引,表锁也是自动加的。

锁用途:

  • 共享锁(S锁、读锁):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。即多个客户可以同时读取同一个资源,但不允许其他客户修改。
  • 排他锁(X锁、写锁):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的读锁和写锁。写锁是排他的,写锁会阻塞其他的写锁和读锁

 

 

间隙锁GAP

当我们用范围条件检索数据而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合范围条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在 的记录,叫做“间隙(GAP)”。InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁。例子:假如emp表中只有101条记录,其empid的值分别是1,2,...,100,101

InnoDB使用间隙锁的目的有2个:

  • 为了防止幻读(Repeatable read隔离级别下再通过GAP锁即可避免了幻读) ,会让插入间隙的sql语句阻塞,数据插入不了
  • 满足恢复和复制的需要:MySQL的恢复机制要求在一个事务未提交前,其他并发事务不能插入满足其锁定条件的任何记录,也就是不允许出现幻读

 

死锁

2+个线程在执行过程中, 因争夺资源而造成的相互等待的现象,若无外力作用,它们将无法推进下去。

 

 

Use SHOW INNODB STATUS来确定最后一个死锁的原因。

 

死锁避免:

1.以固定的顺序访问表和行

2.大事务拆小,大事务更容易产生死锁

3.在一次事务中尽可能做到一次锁所需要的所有资源,减少死锁概率

4.用更低的隔离级别;

5.使用更少的锁定。

 

标签:语句,事务,隔离,死锁,提交,级别
来源: https://www.cnblogs.com/SEU-ZCY/p/16506331.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有