事务便是一组原子性的SQL查询,或者说一个独立的事情单元
原子性(Atomicity):
事务是数据库的逻辑事情单位,它对数据库的修正要么全部实行,要么全部不实行。

同等性(Consistemcy):
事务前后,数据库的状态都知足所有的完全性约束。
隔离性(Isolation):
并发实行的事务是隔离的,一个不影响一个。如果有两个事务,运行在相同的韶光内,实行相同的功能,事务的隔离性将确保每一事务在系统中认为
只有该事务在利用系统。这种属性有时称为串行化,为了防止事务操作间的稠浊,必须串行化或序列化要求,使得在同一韶光仅有一个要求用于同一数据。
通过设置数据库的隔离级别,可以达到不同的隔离效果。
持久性(Durability):
在事务完成往后,该事务所对数据库所作的变动便持久的保存在数据库之中,并不会被回滚。
注:关于同等性可能有些人不太理解,OK,我再来举个例子阐明一下
A向B转账,假设转账之前这两个用户的钱加起来统共是2000,那么A向B转账之后,不管这两个账户怎么转,A用户的钱和B用户的钱加起来的总额还是2000,这个便是事务的同等性。
二、事务的并发问题
1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
3、幻读:系统管理员A将数据库中所有学生的成绩从详细分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条详细分数的记录,当系统管理员A改结束后创造还有一条记录没有改过来,就彷佛发生了幻觉一样,这就叫幻读。
小结:不可重复读的和幻读很随意马虎稠浊,不可重复读侧重于修正,幻读侧重于新增或删除。办理不可重复读的问题只需锁住知足条件的行,办理幻读须要锁表
三、MySQL事务隔离级别
Read Uncommitted(读取未提交内容)
在该隔离级别,所有事务都可以看到其他未提交事务的实行结果。本隔离级别很少用于实际运用,由于它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它知足了隔离的大略定义:一个事务只能瞥见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),由于同一事务的其他实例在该实例处理其间可能会有新的commit,以是同一select可能返回不同结果。
Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。大略的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会创造有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发掌握(MVCC,Multiversion Concurrency Control)机制办理了该问题。
Serializable(可串行化)
这是最高的隔离级别,它通过逼迫事务排序,使之不可能相互冲突,从而办理幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时征象和锁竞争。
然后是关于数据库的各种锁的总结:
1.共享锁(又称读锁)、排它锁(又称写锁):
InnoDB引擎的锁机制:InnoDB支持事务,支持行锁和表锁用的比较多,Myisam不支持事务,只支持表锁。
共享锁(S):许可一个事务去读一行,阻挡其他事务得到相同数据集的排他锁。
排他锁(X):许可得到排他锁的事务更新数据,阻挡其他事务取得相同数据集的共享读锁和排他写锁。
意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
解释:
1)共享锁和排他锁都是行锁,意向锁都是表锁,运用中我们只会利用到共享锁和排他锁,意向锁是mysql内部利用的,不须要用户干预。
2)对付UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对付普通SELECT语句,InnoDB不会加任何锁,事务可以通过以下语句显示给记录集加共享锁或排他锁。
共享锁(S):SELECT FROM table_name WHERE ... LOCK IN SHARE MODE。
排他锁(X):SELECT FROM table_name WHERE ... FOR UPDATE。
对付锁定行记录后须要进行更新操作的运用,该当利用Select...For update 办法,获取排它锁。(用共享锁,在读了之后再写会壅塞,会导致去世锁)
这里说说Myisam:MyISAM在实行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在实行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁。
3)InnoDB行锁是通过给索引上的索引项加锁来实现的,因此InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才利用行级锁,否则,InnoDB将利用表锁!
2.乐不雅观锁、悲观锁:
悲观锁:悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修正持守旧态度,因此,在全体数据处理过程中,将数据处于锁定状态。悲观锁的实现,每每依赖数据库供应的锁机制(也只有数据库层供应的锁机制才能真正担保数据访问的排他性,否则,纵然在本系统中实现了加锁机制,也无法担保外部系统不会修正数据)
1)利用悲观锁,我们必须关闭mysql数据库的自动提交属性,采取手动提交事务的办法,由于MySQL默认利用autocommit模式,也便是说,当你实行一个更新操作后,MySQL会急速将结果进行提交。
2)须要把稳的是,在事务中,只有SELECT ... FOR UPDATE 或LOCK IN SHARE MODE 同一笔数据时会等待其它事务结束后才实行,一样平常SELECT ... 则不受此影响。对付UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X)。
3)补充:MySQL select…for update的Row Lock与Table Lock
利用select…for update会把数据给锁住,不过我们须要把稳一些锁的级别,MySQL InnoDB默认Row-Level Lock,以是只有「明确」地指定主键(或有索引的地方),MySQL 才会实行Row lock (只锁住被选取的数据) ,否则MySQL 将会实行Table Lock (将全体数据表单给锁住)。
乐不雅观锁:
乐不雅观锁( Optimistic Locking ) 相对悲观锁而言,乐不雅观锁假设认为数据一样平常情形下不会造成冲突,以是在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果创造冲突了,则让返回用户缺点的信息,让用户决定如何去做(一样平常是回滚事务)。那么我们如何实现乐不雅观锁呢,一样平常来说有以下2种办法:
1).利用数据版本(Version)记录机制实现,这是乐不雅观锁最常用的一种实现办法。何谓数据版本?即为数据增加一个版本标识,一样平常是通过为数据库表增加一个数字类型的 “version” 字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断数据库表对应记录确当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据。
2).乐不雅观锁定的第二种实现办法和第一种差不多,同样是在须要乐不雅观锁掌握的table中增加一个字段,名称无所谓,字段类型利用韶光戳(timestamp), 和上面的version类似,也是在更新提交的时候检讨当前数据库中数据的韶光戳和自己更新前取到的韶光戳进行比拟,如果同等则OK,否则便是版本冲突。
总结:两种锁各有优缺陷,不可认为一种好于另一种,像乐不雅观锁适用于写比较少的情形下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的全体吞吐量。但如果常常产生冲突,上层运用会不断的进行retry,这样反倒是降落了性能,以是这种情形下用悲观锁就比较得当。
其余,高并发情形下个人认为乐不雅观锁要好于悲观锁,由于悲观锁的机制使得各个线程等待韶光过长,极其影响效率,乐不雅观锁可以在一定程度长进步并发度。
3.表锁、行锁
表级锁(table-level locking):MyISAM和MEMORY存储引擎
行级锁(row-level locking) :InnoDB存储引擎
页面锁(page-level-locking):BDB存储引擎
表级锁:开销小,加锁快;不会涌现去世锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会涌现去世锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁:开销和加锁韶光界于表锁和行锁之间;会涌现去世锁;锁定粒度界于表锁和行锁之间,并发度一样平常。