3、数据库的事务、并发和锁机制
1、事务
概念:
用户定义的一个数据库操作序列,这些操作要么全做、要么全不做,是不可分割的工作单位,同时事务也是恢复和并发控制的基本单位。
定义事务语句:
begin transaction;开始事务。
commit;提交,即提交事务所有操作,将事务中所有的对数据库的更新写回到磁盘中去。
rollback;回滚,即撤销对事务的所有操作,回滚到事务的开始状态。
事务特性:ACID
原子性:
事务中包括的操作要么都做要么都不做。
一致性:
事务执行的结果必须使事务从一个一致状态转变到另一个一致状态。数据库中只包含成功事务提交的结果时,就说数据库处于一致性状态。A账户给B账户转一万块钱,这个事务涉及两个操作,A账户减1万,B账户加1万,如果这两个操作都做那么就是一致的,如果只做其中一个那么肯定是不一致的。
隔离性:
并发事务之间是互不影响,即我这个事务内部操作和使用的数据和别的事务没有半毛钱关系。
持续性:
一旦提交,那么我这个事务对数据库的改变就应该是永久的。
2、并发
分类:
交叉并发:单处理机事务交叉执行,假并行,只是减少处理机空闲时间。(后续讨论基于此情况)
同时并发:多处理机事务同时执行,真并行。
并发的异常情型:
第一类丢失更新:A count=count+1 commit;B count=count-1 rollback;A事务的操作被丢失。
脏读:A 100->100+1 没提交 B开始读到101,A rollback; B读到的数就是脏读数据。
不可重复读:第一次:A读count 100 后B改count=count+1 第二次:A再读,两次结果不一样。
第二类丢失更新:A count=count+1 commit;B count=count+2 commit;A事务被丢失。
幻读:A 第一次查一个表中的数据行数count;B 向表中添加一行数据,A再次读count,A两次读到的数据不一致。
3、事务的隔离级别:
读未提交(Read Uncommitted):该隔离级别指即使一个事务的更新语句没有提交,但是别的事务可以读到这个改变,几种异常情况都可能出现。极易出错,没有安全性可言,基本不会使用。
读已提交(Read Committed):该隔离级别指一个事务只能看到其他事务的已经提交的更新,看不到未提交的更新,消除了脏读和第一类丢失更新,这是大多数数据库的默认隔离级别,如Oracle,Sqlserver。
可重复读(Repeatable Read):该隔离级别指一个事务中进行两次或多次同样的对于数据内容的查询,得到的结果是一样的,但不保证对于数据条数的查询是一样的,只要存在读改行数据就禁止写,消除了不可重复读和第二类更新丢失,这是Mysql数据库的默认隔离级别。
串行化(Serializable):意思是说这个事务执行的时候不允许别的事务并发执行.完全串行化的读,只要存在读就禁止写,但可以同时读,消除了幻读。这是事务隔离的最高级别,虽然最安全最省心,但是效率太低,一般不会用。
4、锁机制:数据库的隔离级别实现一般是通过数据库锁实现的。
总分类:
乐观锁:
一般是指用户自己实现的一种锁机制,比如hibernate实现的乐观锁甚至编程语言也有乐观锁的思想的应用。
悲观锁:
认为数据随时会修改,所以整个数据处理中需要将数据加锁。悲观锁一般都是依靠关系数据库提供的锁机制,事实上关系数据库中的行锁,表锁不论是读写锁都是悲观锁。
悲观锁按作用范围再分:
行锁:
锁的作用范围是行级别,数据库能够确定那些行需要锁的情况下使用行锁,如果不知道会影响哪些行的时候就会使用表锁。举个例子,一个用户表user,有主键id和用户生日birthday当你使用update … where id=?这样的语句数据库明确知道会影响哪一行,它就会使用行锁,当你使用update … where birthday=?这样的的语句的时候因为事先不知道会影响哪些行就可能会使用表锁。
表锁:
锁的作用范围是整张表。
悲观锁按使用性质再分:
共享锁(Share locks简记为S锁):
也称读锁,事务A对对象T加s锁,其他事务也只能对T加S,多个事务可以同时读,但不能有写操作,直到A释放S锁。
排它锁(Exclusivelocks简记为X锁):
也称写锁,事务A对对象T加X锁以后,其他事务不能对T加任何锁,只有事务A可以读写对象T直到A释放X锁。
更新锁(简记为U锁):
用来预定要对此对象施加X锁,它允许其他事务读,但不允许再施加U锁或X锁;当被读取的对象将要被更新时,则升级为X锁,主要是用来防止死锁的。因为使用共享锁时,修改数据的操作分为两步,首先获得一个共享锁,读取数据,然后将共享锁升级为排它锁,然后再执行修改操作。这样如果同时有两个或多个事务同时对一个对象申请了共享锁,在修改数据的时候,这些事务都要将共享锁升级为排它锁。这些事务都不会释放共享锁而是一直等待对方释放,这样就造成了死锁。如果一个数据在修改前直接申请更新锁,在数据修改的时候再升级为排它锁,就可以避免死锁。
乐观锁:
顾名思义,就是很乐观,每次自己操作数据的时候认为没有人回来修改它,所以不去加锁,但是在更新的时候会去判断在此期间数据有没有被修改,需要用户自己去实现。既然都有数据库提供的悲观锁可以方便使用为什么要使用乐观锁呢?对于读操作远多于写操作的时候,大多数都是读取,这时候一个更新操作加锁会阻塞所有读取,降低了吞吐量。最后还要释放锁,锁是需要一些开销的,我们只要想办法解决极少量的更新操作的同步问题。换句话说,如果是读写比例差距不是非常大或者你的系统没有响应不及时,吞吐量瓶颈问题,那就不要去使用乐观锁,它增加了复杂度,也带来了额外的风险。
乐观锁实现方式:
版本号(记为version):
就是给数据增加一个版本标识,在数据库上就是表中增加一个version字段,每次更新把这个字段加1,读取数据的时候把version读出来,更新的时候比较version,如果还是开始读取的version就可以更新了,如果现在的version比老的version大,说明有其他事务更新了该数据,并增加了版本号,这时候得到一个无法更新的通知,用户自行根据这个通知来决定怎么处理,比如重新开始一遍。这里的关键是判断version和更新两个动作需要作为一个原子单元执行,否则在你判断可以更新以后正式更新之前有别的事务修改了version,这个时候你再去更新就可能会覆盖前一个事务做的更新,造成第二类丢失更新,所以你可以使用update … where … and version=”old version”这样的语句,根据返回结果是0还是非0来得到通知,如果是0说明更新没有成功,因为version被改了,如果返回非0说明更新成功。
时间戳(timestamp):
和版本号基本一样,只是通过时间戳来判断而已,注意时间戳要使用数据库服务器的时间戳不能是业务系统的时间。
待更新字段:
和版本号方式相似,只是不增加额外字段,直接使用有效数据字段做版本控制信息,因为有时候我们可能无法改变旧系统的数据库表结构。假设有个待更新字段叫count,先去读取这个count,更新的时候去比较数据库中count的值是不是我期望的值(即开始读的值),如果是就把我修改的count的值更新到该字段,否则更新失败。java的基本类型的原子类型对象如AtomicInteger就是这种思想。
所有字段:
和待更新字段类似,只是使用所有字段做版本控制信息,只有所有字段都没变化才会执行更新。
乐观锁几种方式的区别:
新系统设计可以使用version方式和timestamp方式,需要增加字段,应用范围是整条数据,不论那个字段修改都会更新version,也就是说两个事务更新同一条记录的两个不相关字段也是互斥的,不能同步进行。旧系统不能修改数据库表结构的时候使用数据字段作为版本控制信息,不需要新增字段,待更新字段方式只要其他事务修改的字段和当前事务修改的字段没有重叠就可以同步进行,并发性更高。
3、数据库的事务、并发和锁机制相关推荐
- MySQL基础篇(06):事务管理,锁机制案例详解
本文源码:GitHub·点这里 || GitEE·点这里 一.锁概念简介 1.基础描述 锁机制核心功能是用来协调多个会话中多线程并发访问相同资源时,资源的占用问题.锁机制是一个非常大的模块,贯彻MyS ...
- 【MySQL进阶】MySQL事务隔离与锁机制底层原理万字总结(建议收藏!!)
[MySQL进阶]MySQL事务隔离与锁机制底层原理万字总结(建议收藏!!) 参考资料: 美团技术团队:Innodb中事务隔离级别和锁的关系 数据库的锁,到底锁的是什么? 阿里面试:说说一致性读实现原 ...
- 游标、事务并发和锁三者之间的那点事
对数据库学习的不断深入,对游标的认识也在逐渐加深,游标与事务.锁有着密不可分的关系. 无论是事务.锁还是游标相对于数据库来说最主要目的是保证数据的完整性.对事务并发.锁定的深入学习才能更加完善对游标的 ...
- 多线程高并发 底层锁机制与优化的最佳实践——各种锁的分类 || synchronized 关键字 倒底锁的是什么东西?|| CAS与ABA问题||锁优化||轻量级锁一定比重量级锁的性能高吗
多线程高并发 底层锁机制与优化的最佳实践 各种锁的分类 加上synchronized 关键字,共享资源就不会出错 synchronized 关键字 倒底锁的是什么东西? synchronized 锁的 ...
- mysql 事务操作与锁机制
mysql 事务操作与锁机制
- MySQL并发 共享锁目的_mysql并发与锁机制
在InnoDB中,锁是逐步获得的,因此发生死锁是可能的.发生死锁后,InnoDB一般都能自动检测到,并使一个事务释放锁并回退,另外一个事务获得锁,并继续完成事务.但在涉及外部锁,或涉及表锁的情况下,I ...
- 【数据库】MySQL中的锁机制
MySQL中的锁机制 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则. MySQL 数据库由于其自身架构的特点,存在多种数据存储引擎,每种 ...
- 数据库中事务并发问题
对于同时运行的多个事务,当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制.就会导致各种并发问题: 脏读: 对于两个事务T1,T2, T1读取了已经被T2更新但还没有被提交的字段 之后, ...
- 回滚机制_【巨杉数据库SequoiaDB】巨杉 Tech | 并发性与锁机制解析与实践
01 概述 数据库是一个多用户使用的共享资源.当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况.若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性.加锁 ...
最新文章
- Win32API 窗口程序的创建7大步骤
- SAP WORK FLOW
- intellij中重命名一个文件
- java 数据库 事务 只读_java – odd SQLException – 无法检索转换只读状态服务器
- excel插入页码_Excel里毫不起眼的页眉页脚,居然有这3种高能用法!
- java if hasvalue_首选:可为空 .HasValue或Nullable !=空吗?
- IntelliJ IDEA Maven jar包冲突解决,快速发现jar包冲突
- Smarty中直接加JS代码和将JS代码写在literal标签里
- Mesos超配:让集群利用率可以达到100%
- 如何学好C和C++?怎么学习C/C++?学习C和C++的技巧是什么?
- 哈理工oj 1677
- 过滤钩子驱动程序一(微软DDK文档,FLASHSKY翻译)
- Mac下的五笔输入法(完美)
- 高等数学(第七版)同济大学 习题3-4 个人解答(前8题)
- 【CSDN】博文导入微信公众号
- 国内十大不可错过的免费学习资源网站(火速收藏中)
- python爆破ZIP文件(支持纯数字,数字+字母,密码本)
- 电场强度 高斯定理 习题
- linux显卡用amd还是NVIDIA,Linux NVIDIA显卡驱动年度横评,不同于AMD,NVI
- 解决Linux“Device is busy”与磁盘只读