sybase 事务插入时不可查询_InnoDB事务与锁
事务
可以理解为数据库执行的一个最基础的单位,其包含有限的操作命令(crud)。
事务的属性(ACID):事务必须满足四个属性,原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability)
原子性:要么执行完全结束,要么全部不执行。避免数据执行不完全带来的错误数据,所以事务必须具有原子性(commit、rollback)。即在事务A提交之前,如果发生错误,则需要回退到事务执行前的状态。
一致性:指的是事务在执行的前后,数据库的数据一定会保持一致性的状态。可以理解为系统从一种状态转变为另一种状态。事务A在提交之后,对系统的改变,事务B一定会感知到相同的变化。
隔离性:指的是事务之间的执行相互独立。在并发多个事务执行的时候,每个事务内部的操作不会影响到其他的事务。事务的执行可以抽象为串行执行(这里是修改上的串行)。针对不同情况,事务的隔离会有不同的隔离级别。
持久性:事务一旦提交成功就会被更新到到数据库,不会再被回退。
=================================================================
事务的隔离性级别:
针对并发执行的事务,会出现以下问题:(脏读、不可重复读、幻读)
1.脏读:事务A读取事务B更新的数据,数据B进行了回滚操作,那么A读取到的数据是回滚前的数据是脏数据。
2.不可重复读:在一次事务中,前后两次查询的数据不一致。主要是在事务未提交前,有其他的事务进行了更新提交操作。
3.幻读:事务A在对系统进行更新以后,事务B对系统进行了插入或者删除操作,导致事务A发现仍有数据未更新,如同幻觉。
四种事务隔离级别:(处理并发问题)
隔离级别 脏读 不可重复读 幻读
读未提交 是 是 是
读已提交 否 是 是
可重复读 否 否 是
可串行化 否 否 否
读未提交(Read Uncommitted):在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。事务A可以读取事务B未提交的数据,如果事务B回滚,此时A读取的数据即为脏数据。
读已提交(Read Committed):事务A只能读取事务B,或者其他事务已经提交的数据。所以不会出现脏读的数据,但是会出现前后两次不一致的不可重复读,或者幻读。
可重复读 (Repeatable Read):这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。这是因为MVCC机制,select读取不会更改版本号,是快照读,而insert、update和delete会更新版本号,是当前读(当前版本)(注意,这里不会破坏数据的一致性)。无法解决幻读的现象。
可串行化(Serializable):当事务A开启此隔离的级别时候,当其他事务插入一条记录报错,表会被锁了插入失败,mysql中事务隔离级别为serializable时会锁整个表,防止幻读的出现,但是完全的串行换操作会导致效率极低,一般不会使用此隔离级别。
=================================================================
设置全局事务隔离级别:
>SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
>SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
>SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
>SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
设置当前会话事务隔离级别:
>set session transaction isolation level READ UNCOMMITTED;
>set session transaction isolation level READ COMMITTED;
>set session transaction isolation level REPEATABLE READ;
>set session transaction isolation level SERIALIZABLE;
查询事务隔离级别分析工具:
>show variables like '%iso%';
>select @@global.transaction_isolation;
事务隔离级别加锁分析
锁的类型:
锁模式
共享锁(share(S) Lock):
SELECT ... LOCK IN SHARE MODE
- 排他锁(exclusive(X) Lock):
SELECT * FROM table_name WHERE … FOR UPDATE
- 意向锁(Intention Locks):表级别的锁,自动施加,自动释放。
锁在细力度上又可以分为 表锁和行锁
共享锁(share(S) Lock):共享锁,顾名思义此对象锁是可以共享的,即事务A对数据加上共享锁以后,其它事务也可以加上共享锁,但是不能加排它锁。共享锁只能读,不能修改数据。(行锁)。
排他锁(exclusive(X) Lock):当且只有一个事务可以对数据加锁,而其他事务不能再加任何类型的锁,排他锁可以读,也可以写。(行锁)。
意向锁(Intention Locks):表级别的锁,是在数据库的某行加锁(s或者x)的获取时候,自动加上意向锁(IS或者IX),记录有此类(s或者x)锁。(表级别锁不会和行级别锁冲突)
为什么要使用意向锁:当事务要加入一个表级锁的时候,我们需要遍历每一行看一看是否有其他锁防止冲突,如果数据量较大那么性能将会极低,所以加上意向锁可以直接判断是否有意向锁即可。
获得锁
1.事务在获得某个数据的S锁,必须先获得一个IS或者更强的锁
2.事务在获得某个数据的X锁,必须先获得表的IX锁
加锁
事务在加入表级锁时,先判断是否有X、IX、S、IS锁,有则失败
X IX S IS
X Conflict Conflict Conflict Conflict
IX Conflict Compatible Conflict Compatible
S Conflict Conflict Compatible Compatible
IS Conflict Compatible Compatible Compatible
可以看出,共享锁S是兼容S和IS的。IS与IX意向锁是对表加锁相互兼容的。
=================================================================
锁的类型
记录锁(Record Locks):innoDB的行锁是对索引的加锁,innoDB是一个聚簇索引使用的是B+树来进行实现的,所以innoDB的锁只有在使用索引的条件时候,才会加锁,即便是不同行但是相同索引也会有冲突。当不使用索引时,则会使用表锁。
间隙锁(Gap Locks):对索引项之间的"间隙"加锁,不包括索引项本身(左右开区间)。e.g. SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; GAP锁会阻止其他事务进行的插入操作,不会阻止其他事务获取相同间隙的gap锁并且gap S-lock和gap X-lock不冲突。
Next-Key Locks : Next-Key 锁 = 记录锁+间隙锁。锁定一个范围并且锁定记录本身索引。InnoDB的默认加锁方式。
插入意向锁(Insert Intention Locks):是间隙锁的一种,在插入一条记录之前,需要先拿到插入间隙的插入意向锁。当其他事务持有目标间隙的Gap锁时会阻塞。
=================================================================
MVCC(Multiversion Concurrency Control)多版本并发控制
作用:实现了读不加锁不会导致阻塞,写加锁,读写不冲突,在读多写少的场景下极大的提高了其效率,增加了其并发性。RC和RR级别使用。
实现:在每一行记录的后面增加两个隐藏列,记录创建版本号和删除版本号。每个事务都有唯一的递增版本号,那么每一操作的创建版本号或者删除版本号都会使用事务的版本号。
=================================================================
- INSERT:InnoDB为每个新增行记录当前事务编号作为创建ID
- UPDATE:记录修改当前行的值,写事务编号,回滚指针指向undo log中的修改前的行
- DELETE:将删除位置为删除
- SELECT:查询出数据行的版本小于等于当前事务的版本号的数据,如删除位为删除则表示已删除
1.创建一个name=sql的数据,事务号为1
>insert into test (name) values(1);
id name create version delete version
1 sql 1
2.接着更新 这个数据,使得name=innodb,其事务版本号为2。
具体操作 先把以前这条数据删除,在插入新的数据,使用版本号来标记
>update test set name= 'innodb' where id=1;
id name create version delete version
1 sql 1 2 (代表 这条数据已经被删除)
1 innodb 2
3.删除操作,事务版本号为3
>delete test where id = 1;
id name create version delete version
1 sql 1 2 (代表 这条数据已经被删除)
1 innodb 2 3 (代表 这条数据已经被删除)
4.查询条件: 创建版本号 < 当前版本号 < 删除版本号
RR:在RR的时候,读的是当前的快照表,读取的是固定版本(第一次select的版本)的数据,所以一个事务内的读是一致的。但是 insert update delete操作的是当前读,是最新版本的数据。(快照读)
RC:读事务每次都读取最近的版本,因此两次对同一字段的读可能读到不同的数据(幻读),但能保证每次都读到最新的数据。(当前读)
快照读:读到的数据可能是历史版本数据。
当前读:读到的数据是最近版本数据,特殊的读操作,插入/更新/删除操作,属于当前读需要加锁。
=================================================================
针对隔离级别加锁分析
RU: Select不加锁,写加X锁
RC: Select快照读不加锁,写加X锁
RR: Select快照读不加锁,写加X Next-key锁
Serializable: Select加S Next-key锁,写加X Next-key锁
=================================================================
RU与RC:区别在于快照读与无快照读
RC与RR:一致性读肯定是读取在某个时间点已经提交了的数据,RC的时间点为当前时间点,RR的时间点是第一次select的时间点
RR与Serializable:RR通过快照读,读取的都是过去某个时间点的快照,而Serializable级别下都是加了S锁的读,督导的都是当前时间点的,这意味着在提交前,其他事务无法进行提交。
=================================================================
死锁
从图中,可以看到一个Update操作的具体流程:当Update SQL被发给MySQL后,MySQL Server会根据where条件,读取第一条满足条件的记录,然后InnoDB引擎会将第一条记录返回,并加锁(current read).待MySQL Server收到这条加锁的记录之后,会再发起一个Update请求,更新这条记录.一条记录操作完成,再读取下一条记录,直至没有满足条件的记录为止.因此,Update操作内部,就包含了一个当前读.
注:根据上图的交互,针对一条当前读的SQL语句,InnoDB与MySQL Server的交互,是一条一条进行的,因此,加锁也是一条一条进行的.先对一条满足条件的记录加锁,返回给MySQL Server,做一些DML操作;然后在读取下一条加锁,直至读取完毕.
单个SQL组成的事务,从宏观上来看,锁是在这个语句上一次获得的,但从底层实现上来看,是逐个记录行查询,得到符合条件的记录即对该行记录的索引加锁.,而加锁的过程是边查边加、逐行获得。
这个一个数据库的设计原则,说的是锁操作分为两个阶段:加锁阶段与解锁阶段,并且保证加锁阶段与解锁阶段不相交。在一个事务中先加锁执行完操作,再统一在commit前释放所有的锁。
RC与RR的区别,RC级别下不会加GAP锁,RR级别下会加GAP锁
两个表、两行记录,交叉获得和申请互斥锁,相同表记录行锁冲突:事务A按照一定顺序加锁,事务B按照相反的顺序加锁就会出现死锁
如何避免死锁
- 在程序中添加对死锁的重试
- 完成相关变动后尽早提交事务
- 修改多表或同表的多行数据时,按照一定的顺序
- 添加合适的索引
- 一切都没用则可以使用表锁
sybase 事务插入时不可查询_InnoDB事务与锁相关推荐
- mysql同步三张表如何用事务_MySQL 多表查询与事务的操作
表连接查询 什么是多表查询 # 数据准备 # 多表查询的作用 * 比如:我们想查询孙悟空的名字和他所在的部门的名字,则需要使用多表查询 # 如果一条 SQL 语句查询多张表,因为查询结果在多张不同的表 ...
- 深入浅出事务的本质,附 OceanBase 事务解析14问
作者:颜然,蚂蚁集团资深技术专家 OceanBase 初创成员之一,OceanBase 分布式数据库事务研发负责人,目前负责事务引擎.高可用架构.负载均衡.性能优化等方面的工作. 事务的前世 每个人的 ...
- jpa 事务嵌套事务_JPA 2 | EntityManagers,事务及其周围的一切
jpa 事务嵌套事务 介绍 对我来说,最令人困惑和不清楚的事情之一是,作为Java开发人员,一直是围绕事务管理的谜团,尤其是JPA如何处理事务管理. 事务什么时候开始,什么时候结束,实体的持久化方式, ...
- mysql 事务 返回插入的值_Mysql同一个事务内记录成功插入后查询不出来
背景: 1)mysql:Ver 14.12 Distrib 5.0.45, for Win32 (ia32) 2)mysql odbc驱动:3.51.22 3)vs2005 4)客户端用ado,odb ...
- mysql使用jdbc进行批量插入时把事务设为手动提交比事务自动提交速度快了10倍
第一次写博客,写的不好请多多包涵.欢迎评论 今天需要对mysql做一个批量插入的操作,使用的是原生的jdbc对mysql进行操作,大约插入20几万条数据,刚开始事务是自动提交的,插完数据大约用了4分钟 ...
- mysql隔离级别 简书_InnoDB 事务隔离级别(Mysql篇)
前言: Mysql支持MyISAM和InnoDB两种存储引擎,区别在此就不详细说明.此篇是讲述事务,所以切记自己的table是InnDB.此处大坑! 在Mysql InnoDB 中,事务主要有四种隔离 ...
- Web框架之Django_06 模型层了解(F查询、Q查询、事务、update和save、only和defer、choice属性、bulk_create)
阅读目录 一.F查询 二. Q查询 三.事务 四.补充的一些常用的操作 摘要: F查询 Q查询 事务 一.F查询 在上面所有的例子中,我们构造的过滤器都只是将字段值与某个我们自己设定的常量做比较.如果 ...
- day15(mysql 的多表查询,事务)
mysql之多表查询 1.合并结果集 作用:合并结果集就是把两个select语句查询的结果连接到一起! /*创建表t1*/ CREATE TABLE t1(a INT PRIMARY KEY ,b V ...
- asp多表查询并显示_MySQL多表查询与事务
回顾 1. DQL单表高级查询条件 where比较运算逻辑运算符in关键字between关键字if null关键字like关键字% 多个任意字符_ 单个任意字符排序 order byascdesc聚合 ...
最新文章
- Installation error: INSTALL_FAILED_VERSION_DOWNGRADE
- 【迈克尔・乔丹:人工智能,革命远未发生】
- DXUT框架剖析(12)
- I/O多路复用——select
- 1.1 基本图像导入、处理和导出
- PHP中文乱码解决办法
- 毕业与计算机专业,电子与计算机工程专业毕业后干什么
- 【JSP】web.xml配置JavaWeb项目首页
- myeclipse下Tomcat java.lang.OutOfMemory Error: Java heap space
- 关于运营Tiktok账号的问题?
- Linux 压缩和解压
- VMware Ubuntu虚拟机卡顿慢 解决方法大全
- fatal: the remote end hung up unexpectedly问题解决办法
- 揭秘:张国荣葬礼,袁咏仪为何哭到失控?
- 专访中国数据科技集团CEO林道进:把无序变有序 让数据更有价
- PCL读取ply文件
- 注册公众号(企业类型的订阅号)参考步骤
- 计算机通讯技术核心期刊有哪些,通信技术专业的核心期刊有哪些
- 数字证书连接服务器异常,连接时Socket.io + SSL +自签名CA证书出现错误
- mysql 数据库视图,Mysql数据库中的视图
热门文章
- 大学计算机测试试题,大学计算机基础 excel测试题 求答案~~喵~~
- win2003能装mysql_Windows2003系统安装mysql小结
- iangularjs 模板_AngularJS 动态模板
- php fpm 日志记录,如何解决nginx下php-fpm不记录php报错日志的问题
- java获取目录中最后被更改的文件_如何使用Java从目录中只获取10个最后修改过的文件?...
- mysql php查询错误_php查询mysql数据库错误
- Python教程:Sys 与 Import 模块
- php安卓交互安全,php结合安卓客户端实现查询交互实例
- signature=5edb6549fd9da7abd1cea3d5008f5c15,IMPLEMENTING INVERTED MASTER-SLAVE 3D SEMICONDUCTOR STACK
- css居父容器下,整理:子容器垂直居中于父容器的方案