事务和锁

Atomic,同一个事务里,要么都提交,要么都回滚
Consistency,即在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏
Isolation,并发事务间的数据是彼此隔离的,通过锁的方式来实现。
Durabiliy,事务提交后,所有结果务必被持久化REDO UNDO

INNODB记录逻辑的操作。

INNODB原理:

事务提供一种机制将一个活动设计的所有的操作纳入一个不可分割的执行单元,

组成事务的所有操作只有在所有操作均能正常执行的情况下提交,只要其中任一操作执行失败,都将导致整个事务回滚,

简单说:事务提供一种机制--“要么什么都不做,要么做全套”的机制

撤销日志,undolog:

undo 工作原理:

主要是为了满足事务的原子性,在操作任何数据前,将数据备份到一个地方-UNDOLOG ,然后进行数据的增、删、改操作,如果出现

了错误或用户执行ROLLBACK语句,系统可以利用UNDO LOG中的备份数据恢复到事务开始之前

重做日志,redolog

redo工作原理:

与UNDOLOG相反,REDOLOG记录的是新数据的备份,在事务提交前,只要将REDOLOG持久化,不需要将数据持久化,当系统奔溃时,虽然数据

没有持久化,但REDOLOG持久化,系统可根据REDOLOG内容,将所有数据恢复到最新的状态。

事务隔离级别可以解决并发操作中存在的问题:

Dirty read (脏读)-- READ-UNCOMMITTED

事务(A)读取到另一个事务(B)中修改后但尚未提交的数据,并这个数据的基础上操作。这时,如果 B事务回滚,那么 A事务读到的数据是无效的。不符合一致性
unrepeatable read(不可重复读)
事务(A)读取到了另一个事务(B)已经提交的更改数据,不符合隔离性

phantom read(幻读)
事务(A)读取到了另一个事务(B)提交的新增数据,不符合隔离性

INNODB采用NEXT-KEY LOCK机制来避免幻读

为了解决 脏读、幻读、不可重复读,我们引入事务隔离级别:
Read Uncommitted(读未提交)--脏读、,不可重复读
Read Commited(读已提交新的数据)--幻读
Repeatable Read(可重复读)--默认隔离级别,消除了脏读、不可重复读、幻读,保证事务一致性
Serializable(串行)--串行化读,每次读都需要获得表级共享锁,读写间相互都会阻塞

RR可能出现幻读主要是参数设置innodb_locks_unsafe_for_binlog=1

日志类型的事务类型可以设置RC

MySQL支持的锁:表锁,行锁、页级锁

INNODB可能发生表锁:

1、auto-inc锁
2、全表更新、全索引更新
3、使用SR事务隔离级别

锁的类型:表锁基于聚集索引的主键

1、record lock(行/记录锁)

单个记录上的锁,有可能是普通索引,唯一索引,组合索引等。
2、gap lock(间隙锁)

在索引记录间隙上的锁,或者是第一条索引记录之前、最后一条索引记录之后上的间隙锁

3、next-key lock (record lock + gap lock)

索引记录锁以及索引之间的间隙锁,2者组合锁


SELECT自动加读锁


其他DML、DDL自动加写锁

InnoDB是通过给索引上的索引项加锁来实现行锁


InnoDB有几种锁:


共享锁(S - LOCKING),允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁


排它锁(X - LOCKING),允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他锁


InnoDB还独有的实现了2种锁:
  意向共享锁(IS),事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁
  意向独占锁(IX),事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁

。。。。。。。。


注意:
 (1)在不通过索引条件查询的时候,InnoDB使用的是表锁(默认地,全表所有行加锁,和表级锁相当,例外条件是 RC + innodb_locks_unsafe_for_binlog 组合选项),而不是细粒度行锁。


(2)由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。

加共享锁:SELECT * FROM xx WHERE … LOCK IN SHARE MODE
加排他锁:SELECT * FROM xx WHERE … FOR UPDAT

由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。应用设计的时候要注意这一点。

S、X、IS、IX,表示的是,本锁和其他锁共存的方式,是互斥还是兼容

RECORD LOCK、GAP LOCK、NEXT-KEY LOCK,表示的是,这些锁要加载的范围,是行记录本身,还是行记录+间隙,甚至更大的范围

1、任何辅助索引上的锁,或者非索引列上的锁,最终都要回溯到主键上,在主键上也要加一把锁
2、任何叶子节点上的S或X锁之前,都会在根节点加一个IS或IX锁,也就是表级别的IS、IX锁
3、主键索引上的锁,都是record lock
4、唯一索引辅助索引上的锁,也都是record lock
5、非唯一索引辅助索引上的锁,则是next-key lock
6、不会有单独的gap lock出现,只会伴随着record lock出现,依附于它

主键索引 = record lock(但外键约束、唯一约束检测仍然使用gap lock)
唯一辅助索引 = record lock(但外键约束、唯一约束检测仍然使用gap lock)
非唯一辅助索引 = next-key lock

上述结论的前提:
| innodb_locks_unsafe_for_binlog | OFF   |
RR级别

如果想降低锁的范围,则可以:
设置RC隔离级别,或者启用innodb_locks_unsafe_for_binlog,可以关闭gap lock(但外键约束、唯一约束检测仍然使用gap lock)


如果辅助索引上的搜索及锁定是排他的,则会回溯到其相应的聚集索引,并且在它上面加锁


对无索引的字段检索更新时,升级成表级锁


SELECT … FROM,一致性非锁定读,除非是SERIALIZABLE隔离级别


SELECT … FROM,一致性非锁定读,除非是SERIALIZABLE隔离级别,在其影响的索引记录上设置一个共享锁


LOCK IN SHARED MODE,使用共享next-key lock


FOR UPDATE使用排他next-key lock锁,会阻止LOCK IN SHARED MODE请求

UPDATE/DELETE,排他next-key lock

INSERT,排他record lock,而非next-key lock,但在写入新记录之前需要加意向插入gap lock(insertion intention gap lock)

INSERT ... ON DUPLICATE KEY UPDATE,排他next-key lock(即将被UPDATE的记录上)

REPLACE,没冲突/重复时,和INSERT一样,否则(有冲突时是先DELETE后INSERT)加next-key lock

INSERT INTO T SELECT ... FROM S WHERE,T表上排他record lock;事务隔离级别为RC或者启用innodb_locks_unsafe_for_binlog并且隔离级别不是SERIALIZABLE时,S表上采用无锁一致性读。否则,加排他next-key lock(RC不加锁,RR加next-key lock)
CREATE TABLE..SELECT,和INSERT…SELECT一样


REPLACE INTO t SELECT ... FROM s WHERE或 UPDATE t ... WHERE col IN (SELECT ... FROM s ...),都会在s表上加next-key lock


AUTO_INCREMENT列上写入新数据时,索引末尾设置排他锁。


AUTO_INCREMENT列上写入新数据时,索引末尾设置排他锁。请求自增列计数器时,InnoDB使用一个AUTO-INC表锁,只对请求的那个SQL有影响,不会影响整个事务。该锁被持有时,其他会话不能往InnoDB表中写入新行


LOCK TABLES,设置表锁


几个重点的锁类型,需要关注下:
  如果辅助索引上的搜索及锁定是排他的,则会取回其相应的聚集索引,并且在它上面加锁
  对无索引的字段检索更新时,升级成表级锁
  SELECT … FROM,一致性非锁定读,除非是SERIALIZABLE隔离级别
   INSERT INTO T SELECT ... FROM S WHERE,T表上排他record lock;事务隔离级别为RC或者启用innodb_locks_unsafe_for_binlog并且隔离级别不是SERIALIZABLE时,S表上采用无锁一致性读。否则,加排他next-key lock
  INSERT,排他record lock,非next-key lock,但加意向插入gap lock(还有一种叫做 意向插入(insertion intention) 的gap lock,如果两个不同事务想往同一个gap lock中写入数据,但写入位置不一样时,是无需等待,可以直接写入的,因为没有冲突)
  AUTO_INCREMENT列上写入新数据时,索引末尾设置排他锁。请求自增列计数器时,InnoDB使用一个AUTO-INC表锁,只对请求的那个SQL有影响,不会影响整个事务。该锁被持有时,其他会话不能往InnoDB表中写入新行

innodb_print_all_deadlocks 选项


设置 innodb_print_all_deadlocks = 1,在日志中记录全部死锁信息


自动检测死锁,并优先回滚小事务(影响较小的事务)


加表锁时,不会发生死锁


事务中,如果SELECT调用存储函数/存储过程失败了,对应的SQL会回滚事务。如果再显式执行ROLLBACK,那么整个事务都回滚。


事务回滚时,会释放全部锁。个别情况下,如果个别SQL因为某些错误回滚事务的话,它所持有的行锁可能无法释放,因为InnoDB的行锁信息并没有记录是哪个SQL持有的,这时候,建议执行一次显式的ROLLBACK


事务中涉及多个表,或者涉及多行记录时,每个事务的操作顺序都要保持一致,降低死锁概率,最好用存储过程/存储函数固化


通过索引等方式优化SQL效率,降低死锁发生概率(减小扫描/锁范围,降低概率)


事务尽快提交,小事务越不容易发生死锁
  加FOR UPDATE、LOCK IN SHARE MODE读锁时,最好降低事务隔离级别,例如用RC级别,降低死锁发生概率


事务中涉及多个表,或者涉及多行记录时,每个事务的操作顺序都要保持一致,降低死锁概率,最好用存储过程/存储函数固化


通过索引等方式优化SQL效率,降低死锁发生概率(减小扫描/锁范围,降低概率)

时间: 2024-10-12 12:45:23

事务和锁的相关文章

数据库-事务和锁

事务 所谓事务是用户定义的一个数据库操作系列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位.例如在关系数据库中,一个事务可以是一条sql语句.一组sql语句或整个程序. 给个栗子: 小IT在网上购物,其付款过程至少包括以下几步数据库操作: 更新客户所购商品的库存信息: 生成订单并且保存到数据库: 更新用户相关信息,例如购物数量等: 正常情况下,操作顺利进行,最终交易成功,那么与交易相关的所有数据库信息也成功更新.但是,如果在这一系列过程中任何一个环节出了差错,例如在更新商品库存

分布式缓存技术redis学习系列(三)——redis高级应用(主从、事务与锁、持久化)

上文<详细讲解redis数据结构(内存模型)以及常用命令>介绍了redis的数据类型以及常用命令,本文我们来学习下redis的一些高级特性. 回到顶部 安全性设置 设置客户端操作秘密 redis安装好后,默认情况下登陆客户端和使用命令操作时不需要密码的.某些情况下,为了安全起见,我们可以设置在客户端连接后进行任何操作之前都要进行密码验证.修改redis.conf进行配置. [[email protected] ~]# vi /usr/local/redis/etc/redis.conf ###

[数据库事务与锁]详解七: 深入理解乐观锁与悲观锁

注明: 本文转载自http://www.hollischuang.com/archives/934 在数据库的锁机制中介绍过,数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性. 乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段. 无论是悲观锁还是乐观锁,都是人们定义出来的概念,可以认为是一种思想.其实不仅仅是关系型数据库系统中有乐观锁和悲观锁的概念,像memcache.hibernate.

oracle事务和锁

数据库事务概括 1. 说明 一组SQL,一个逻辑工作单位,执行时整体修改或者整体回退. 2.事务相关概念 1)事务的提交和回滚:COMMIT/ROLLBACK 2)事务的开始和结束 开始事务:连接到数据库,执行DML.DCL.DDL语句 结束事务: 1. 执行DDL(例如CREATE TABLE),DCL(例如GRANT),系统自动执行COMMIT语句 2. 执行COMMIT/ROLLBACK 3. 退出/断开数据库的连接自动执行COMMIT语句 4. 进程意外终止,事务自动rollback 5

[数据库事务与锁]详解五: MySQL中的行级锁,表级锁,页级锁

注明: 本文转载自http://www.hollischuang.com/archives/914 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足. 在数据库的锁机制中介绍过,在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎).表级锁(MYISAM引擎)和页级锁(BDB引擎 ). 行级锁 行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁.行级锁能大大减少数据库操作的冲突.其加锁粒度最小,但加锁的

SQL Server中的事务与锁

了解事务和锁 事务:保持逻辑数据一致性与可恢复性,必不可少的利器. 锁:多用户访问同一数据库资源时,对访问的先后次序权限管理的一种机制,没有他事务或许将会一塌糊涂,不能保证数据的安全正确读写. 死锁:是数据库性能的重量级杀手之一,而死锁却是不同事务之间抢占数据资源造成的. 不懂的听上去,挺神奇的,懂的感觉我在扯淡,下面带你好好领略下他们的风采,嗅査下他们的狂骚.. 先说事务--概念,分类 用华仔无间道中的一句来给你诠释下:去不了终点,回到原点. 举例说明: 在一个事务中,你写啦2条sql语句,一

SQL Server 事务与锁

了解事务和锁 事务:保持逻辑数据一致性与可恢复性,必不可少的利器. 锁:多用户访问同一数据库资源时,对访问的先后次序权限管理的一种机制,没有他事务或许将会一塌糊涂,不能保证数据的安全正确读写. 死锁:是数据库性能的重量级杀手之一,而死锁却是不同事务之间抢占数据资源造成的. 不懂的听上去,挺神奇的,懂的感觉我在扯淡,下面带你好好领略下他们的风采,嗅査下他们的狂骚.. 先说事务--概念,分类 用华仔无间道中的一句来给你诠释下:去不了终点,回到原点. 举例说明: 在一个事务中,你写啦2条sql语句,一

【转】SQL Server中的事务与锁

原文出处:http://www.cnblogs.com/knowledgesea/p/3714417.html 了解事务和锁 事务:保持逻辑数据一致性与可恢复性,必不可少的利器. 锁:多用户访问同一数据库资源时,对访问的先后次序权限管理的一种机制,没有他事务或许将会一塌糊涂,不能保证数据的安全正确读写. 死锁:是数据库性能的重量级杀手之一,而死锁却是不同事务之间抢占数据资源造成的. 不懂的听上去,挺神奇的,懂的感觉我在扯淡,下面带你好好领略下他们的风采,嗅査下他们的狂骚.. 先说事务--概念,分

sqlite的事务和锁,很透彻的讲解 【转】

原文:sqlite的事务和锁 http://3y.uu456.com/bp-877d38906bec097sf46se240-1.html 事务 事务定义了一组SQL命令的边界,这组命令或者作为一个整体被全部执行,或者都不执行.事务的典型实例是转帐. 事务的范围 事务由3个命令控制:BEGIN.COMMIT和ROLLBACK.BEGIN开始一个事务,之后的所有操作都可以取消.COMMIT使BEGIN后的所有命令得到确认:而ROLLBACK还原BEGIN之后的所有操作.如: sqlite> BEG

Mysql 事务与锁机制

一. 事务四要素 数据库事务正确执行的四个基本要素包括原子性(Atomicity).一致性(Consistency).隔离性(Isolation).持久性(Durability),简称ACID.目前要实现ACID主要有两种方式:一种是Write ahead logging,也就是日志式的方式(现代数据库均基于这种方式):另一种是Shadow paging. 原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节.事务在执行过程中发生错误,会被回滚(Rollback)