百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>数据库> 总结数据库事务与 MySQL 事务
分享文章到:

总结数据库事务与 MySQL 事务

发布时间:01/01 来源:未知 浏览: 关键词:

mysql教程总结数据库事务与 MySQL 事务

引荐(免费):mysql教程

事务特点:ACID

从业务角度动身,对数据库的一组操纵要求保持4个特点:

  • Atomicity(原子性):一个事务必需被视为一个不成分割的最小工作单元,整个事务中的所有操纵要末全部提交成功,要末全部失败回滚,关于一个事务来说,不成能只施行其中的一部分操纵。
  • Consistency(一致性):数据库总是从一个一致性状态转换到另一个一致状态。下面的银行列子会说到。
  • Isolation(隔离性):平常来说,一个事务所做的修改在终究提交之前,对其他事务是不成见的。留意这里的“平常来说”,后面的事务隔离级级别会说到。
  • Durability(耐久性):一旦事务提交,则其所做的修改就会永远留存到数据库中。此时即便系统崩溃,修改的数据也不会丧失。(耐久性的平安性与刷新日志级别也存在必然关系,不一样的级别对应不一样的数据平安级别。)

为了更好地懂得ACID,以银行账户转账为例:

START TRANSACTION;SELECT balance FROM checking WHERE customer_id = 10233276;UPDATE checking SET balance = balance - 200.00 WHERE customer_id = 10233276;UPDATE savings SET balance = balance + 200.00 WHERE customer_id = 10233276;COMMIT;
  • 原子性:要末完全提交(10233276的checking余额减少200,savings 的余额增添200),要末完全回滚(两个表的余额都不发生转变)
  • 一致性:这个例子的一致性表现在 200元不会由于数据库系统运转到第3行之后,第4行此前时崩溃而不翼而飞,由于事务还没有提交。
  • 隔离性:同意在一个事务中的操纵语句会与其他事务的语句隔分开,比方事务A运转到第3行之后,第4行此前,此时事务B去查询checking余额时,它依然能够看到在事务A中被减去的200元(账户钱不变),由于事务A和B是彼此隔离的。在事务A提交此前,事务B视察不到数据的改动。
  • 耐久性:这个很好懂得。
  • 事务的隔离性是通过锁、MVCC等实现 (MySQL锁总结)
  • 事务的原子性、一致性和耐久性则是通过事务日志实现(见下)

事务的隔离级别

并发事务带来的问题

  • 更新丧失(Lost Update):当两个或多个事务选中统一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丧失更新问题 --最后的更新覆盖了由其他事务所做的更新。例如,两个编纂人员制作了统一 文档的电子副本。每个编纂人员独立地更换其副本,然后留存更换后的副本,这样就覆盖了原始文档。 最后留存其更换副本的编纂人员覆盖另一个编纂人员所做的更换。假如在一个编纂人员完成并提交事务此前,另一个编纂人员不克不及拜访同 一文件,则可幸免此问题。
  • 脏读(Dirty Reads):一个事务正在对一笔记录做修改,在这个事务完成并提交前, 这笔记录的数据就处于不一致状态; 这时, 另一个事务也来读取统一笔记录,假如不加操纵,第二个事务读取了这些“脏”数据,并据此做进一步的处置,就会发生未提交的数据依靠关系。这种现象被形象地叫做”脏读”。
  • 不成反复读(Non-Repeatable Reads):一个事务在读取某些数据后的某个时间,再次读取之前读过的数据,却发明其读出的数据已经发生了改动、或某些记载已经被删除了!这种现象就叫做“不成反复读” 。
  • 幻读 (Phantom Reads): 一个事务按雷同的查询前提从新读取之前检索过的数据,却发明其他事务插入了知足其查询前提的新数据,这种现象就称为“幻读” 。

幻读和不成反复读的不同:

  • 不成反复读的重点是修改:在统一事务中,一样的前提,第一次读的数据和第二次读的数据不一样。(由于中心有其他事务提交了修改)
  • 幻读的重点在于新增或者删除:在统一事务中,一样的前提,,第一次和第二次读出来的记载数不一样。(由于中心有其他事务提交了插入/删除)

并发事务处置带来的问题的解决方法:

  • “更新丧失”平常是应当完全幸免的。但防止更新丧失,并不克不及单靠数据库事务操纵器来解决,需要利用程序对要更新的数据加必要的锁来解决,因此,防止更新丧失应当是利用的责任。

  • “脏读” 、 “不成反复读”和“幻读” ,其实都是数据库读一致性问题,必需由数据库供给必然的事务隔离机制来解决:

  • 一种是加锁:在读取数据前,对其加锁,阻挠其他事务对数据停止修改。

  • 另一种是数据多版本并发操纵(MultiVersion Concurrency Control,简称 MVCC 或 MCC),也称为多版本数据库:不消加任何锁, 通过必然机制生成一个数据恳求时间点的一致性数据快照 (Snapshot), 并用这个快照来供给必然级别 (语句级或事务级) 的一致性读取。从会员的角度来看,仿佛是数据库可以供给统一数据的多个版本。

SQL标准定义了4类隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不成见的。初级别的隔离级一样支撑更高的并发处置,并具有更低的系统开销。

第1级别:Read Uncommitted(读取未提交内容)

  • 所有事务都可以看到其他未提交事务的施行结果
  • 本隔离级别很少用于实际利用,由于它的机能也不比其他级别好多少
  • 该级别激发的问题是——脏读(Dirty Read):读取到了未提交的数据

第2级别:Read Committed(读取提交内容)

  • 这是大多数数据库系统的默许隔离级别(但不是MySQL默许的)

  • 它知足了隔离的简便定义:一个事务只能看见已经提交事务所做的改动

  • 这种隔离级别显现的问题是——不成反复读(Nonrepeatable Read):不成反复读意味着我们在统一个事务中施行完全雷同的select语句时大概看到不一样的结果。致使这种状况的缘由大概有:

  • 有一个穿插的事务有新的commit,致使了数据的改动;

  • 一个数据库被多个实例操纵时,统一事务的其他实例在该实例处置其间大概会有新的commit

第3级别:Repeatable Read(可重读)

  • 这是MySQL的默许事务隔离级别
  • 它确保统一事务的多个实例在并发读取数据时,会看到一样的数据行
  • 此级别大概显现的问题——幻读(Phantom Read):当会员读取某一范畴的数据行时,另一个事务又在该范畴内插入了新行,当会员再读取该范畴的数据行时,会发明有新的“幻影” 行
  • InnoDB和Falcon储备引擎通过多版本并发操纵(MVCC,Multiversion Concurrency Control)机制解决幻读问题;InnoDB还通过间隙锁解决幻读问题

多版本并发操纵 :

Mysql的大多数事务型储备引擎实现都不是简便的行级锁。基于晋升并发性思考,一样都同时实现了多版本并发操纵(MVCC),包罗Oracle、PostgreSQL。不外实现各不雷同。

MVCC的实现是通过留存数据在某一个时间点快照来实现的。也就是说不管实现时间多长,每个事物看到的数据都是一致的。

分为悲观(optimistic)并发操纵和悲不雅(pressimistic)并发操纵。

MVCC是怎样工作的:

InnoDB的MVCC是通过在每行记载后面留存两个潜藏的列来实现。这两个列一个留存了行的创立时间,一个留存行的过期时间(删除时间)。当然储备的并不是真实的时间而是系统版本号(system version number)。每开端一个新的事务,系统版本号都会主动新增。事务开端时刻的系统版本号会作为事务的版本号,用来查询到每行记载的版本号停止比力。

REPEATABLE READ(可重读)隔离级别下MVCC怎样工作:

  • SELECT

InnoDB会按照以下前提检查每一行记载:

  1. InnoDB只查寻版本早于当前事务版本的数据行,这样可以确保事务读取的行要末是在开端事务此前已经存在要末是事务本身插入或者修改正的
  2. 行的删除版本号要末不决义,要末大于当前事务版本号,这样可以确保事务读取到的行在事务开端此前未被删除

只要相符上述两个前提的才会被查询出来

  • INSERT

InnoDB为新插入的每一行留存当前系统版本号作为行版本号

  • DELETE

InnoDB为删除的每一行留存当前系统版本号作为行删除标识

  • UPDATE

InnoDB为插入的一行新纪录留存当前系统版本号作为行版本号,同时留存当前系统版本号到本来的行作为删除标识

留存这两个版本号,使大多数操纵都不消加锁。使数据操纵简便,机能很好,并且能包管只会读取到复合要求的行。不足之处是每行记载都需要额外的储备空间,需要做更多的行检查工作和一些额外的保护工作。

MVCC只在COMMITTED READ(读提交)和REPEATABLE READ(可反复读)两种隔离级别下工作。

可以认为MVCC是行级锁一个变种,但是他许多状况下幸免了加锁操纵,开销更低。虽然不一样数据库的实现机制有所不一样,但大都实现了非堵塞的读操纵(读不消加锁,且能幸免显现不成反复读和幻读),写操纵也只锁定必要的行(写必需加锁,不然不一样事务并发写会致使数据不一致)。

第4级别:Serializable(可串行化)

  • 这是最高的隔离级别
  • 它通过强迫事务排序,使之不成能彼此冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上同享锁。MySQL锁总结
  • 在这个级别,大概致使大量的超时现象和锁竞争

隔离级别比力

各详细数据库并不必然完全实现了上述 4 个隔离级别,例如:

  • Oracle 只供给 Read committed 和 Serializable 两个标准隔离级别,别的还供给本人定义的 Read only 隔离级别;

  • SQL Server 除支撑上述 ISO/ANSI SQL92 定义的 4 个隔离级别外,还支撑一个叫做“快照”的隔离级别,但严厉来说它是一个用 MVCC 实现的 Serializable 隔离级别。

  • MySQL 支撑全部 4 个隔离级别,但在详细实现时,有一些特点,比方在一些隔离级别下是采纳 MVCC一致性读,但某些状况下又不是。

  • Mysql可以通过施行 set transaction isolation level命令来设定隔离级别,新的隔离级别会鄙人一个事务开端的时候生效。 例如:set session transaction isolation level read committed;

事务日志

事务日志可以帮忙提高事务效力:

  • 使用事务日志,储备引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行动记载到耐久在硬盘上的事务日志中,而不消每次都将修改的数据本身耐久到磁盘。
  • 事务日志采纳的是追加的方式,因此写日志的操纵是磁盘上一小块区域内的次序I/O,而不像随机I/O需要在磁盘的多个地方移动磁头,所以采纳事务日志的方式相对来说要快得多。
  • 事务日志耐久今后,内存中被修改的数据在后台可以渐渐刷回到磁盘。
  • 假如数据的修改已经记载到事务日志并耐久化,但数据本身没有写回到磁盘,此时系统崩溃,储备引擎在重新启动时能够主动复原这一部分修改的数据。

当前来说,大多数储备引擎都是这样实现的,我们平常称之为预写式日志(Write-Ahead Logging),修改数据需要写两次磁盘。

Mysql中的事务实现道理

事务的实现是基于数据库的储备引擎。不一样的储备引擎对事务的支撑程度不一样。mysql中支撑事务的储备引擎有innoDB和NDB。

innoDB是mysql默许的储备引擎,默许的隔离级别是RR(Repeatable Read),并且在RR的隔离级别下更进一步,通过多版本并发操纵(MVCC,Multiversion Concurrency Control )解决不成反复读问题,加上间隙锁(也就是并发操纵)解决幻读问题。因此innoDB的RR隔离级别其实实现了串行化级别的结果,并且保存了比力好的并发机能。

事务的隔离性是通过锁实现,而事务的原子性、一致性和耐久性则是通过事务日志实现。说到事务日志,不得不说的就是redo和undo。

1.redo log

在innoDB的储备引擎中,事务日志通过重做(redo)日志和innoDB储备引擎的日志缓冲(InnoDB Log Buffer)实现。事务开启时,事务中的操纵,都会先写入储备引擎的日志缓冲中,在事务提交此前,这些缓冲的日志都需要提早刷新到磁盘上耐久化,这就是DBA们口中常说的“日志先行”(Write-Ahead Logging)。当事务提交之后,在Buffer Pool中映射的数据文件才会渐渐刷新到磁盘。此时假如数据库崩溃或者宕机,那么当系统重新启动停止复原时,就可以按照redo log中记载的日志,把数据库复原到崩溃前的一个状态。未完成的事务,可以连续提交,也可以选中回滚,这基于复原的战略而定。

在系统启动的时候,就已经为redo log分配了一块持续的储备空间,以次序追加的方式记载Redo Log,通过次序IO来改善机能。所有的事务同享redo log的储备空间,它们的Redo Log按语句的施行次序,顺次交替的记载在一起。如下一个简便示例:

记载1:<trx1, insert…>

记载2:<trx2, delete…>

记载3:<trx3, update…>

记载4:<trx1, update…>

记载5:<trx3, insert…>

2.undo log

undo log主要为事务的回滚效劳。在事务施行的历程中,除了记载redo log,还会记载必然量的undo log。undo log记载了数据在每个操纵前的状态,假如事务施行历程中需要回滚,就可以按照undo log停止回滚操纵。单个事务的回滚,只会回滚当前事务做的操纵,并不会影响到其他的事务做的操纵。

以下是undo+redo事务的简化历程

假设有2个数值,离别为A和B,值为1,2

1. start transaction;

2. 记载 A=1 到undo log;

3. update A = 3;

4. 记载 A=3 到redo log;

5. 记载 B=2 到undo log;

6. update B = 4;

7. 记载B = 4 到redo log;

8. 将redo log刷新到磁盘

9. commit

在1-8的任意一步系统宕机,事务未提交,该事务就不会对磁盘上的数据做任何影响。假如在8-9之间宕机,复原之后可以选中回滚,也可以选中连续完成事务提交,由于此时redo log已经耐久化。若在9之后系统宕机,内存映射中变动的数据还来不及刷回磁盘,那么系统复原之后,可以按照redo log把数据刷回磁盘。

所以,redo log其实保证的是事务的耐久性和一致性,而undo log则保证了事务的原子性。

Mysql中的事务使用

MySQL的效劳层不治理事务,而是由基层的储备引擎实现。比方InnoDB。

MySQL支撑当地事务的语句:

START TRANSACTION | BEGIN [WORK] COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE] ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE] SET AUTOCOMMIT = {0 | 1}
  • START TRANSACTION 或 BEGIN 语句:开端一项新的事务。
  • COMMIT 和 ROLLBACK:用来提交或者回滚事务。
  • CHAIN 和 RELEASE 子句:离别用来定义在事务提交或者回滚之后的操纵,CHAIN 会马上启动一个新事物,并且和方才的事务具有雷同的隔离级别,RELEASE 则会断开和客户端的连接。
  • SET AUTOCOMMIT 可以修改当前连接的提交方式, 假如设定了 SET AUTOCOMMIT=0,则设定之后的所有事务都需要通过明白的命令停止提交或者回滚

事务使用留意点:

  • 假如在锁表期间,用 start transaction 命令开端一个新事务,会造成一个隐含的 unlock
    tables 被施行。
  • 在统一个事务中,最好不使用不一样储备引擎的表,不然 ROLLBACK 时需要对非事
    务类型的表停止特殊的处置,由于 COMMIT、ROLLBACK 只能对事务类型的表停止提交和回滚。
  • 和 Oracle 的事务治理雷同,所有的 DDL 语句是不克不及回滚的,并且部分的 DDL 语句会造成隐式的提交。
  • 在事务中可以通过定义 SAVEPOINT(例如:mysql> savepoint test; 定义 savepoint,名称为 test),指定回滚事务的一个部分,但是不克不及指定提交事务的一个部分。关于复杂的利用,可以定义多个不一样的 SAVEPOINT,知足不一样的前提时,回滚
    不一样的 SAVEPOINT。需要留意的是,假如定义了雷同名字的 SAVEPOINT,则后面定义的SAVEPOINT 会覆盖此前的定义。关于不再需要使用的 SAVEPOINT,可以通过 RELEASE SAVEPOINT 命令删除 SAVEPOINT, 删除后的 SAVEPOINT, 不克不及再施行 ROLLBACK TO SAVEPOINT命令。

主动提交(autocommit):
Mysql默许采纳主动提交模式,可以通过设定autocommit变量来启用或禁用主动提交模式

  • 隐式锁定

InnoDB在事务施行历程中,使用两阶段锁和谈:

随时都可以施行锁定,InnoDB会按照隔离级别在需要的时候主动加锁;

锁只要在施行commit或者rollback的时候才会开释,并且所有的锁都是在统一时刻被开释。

  • 显式锁定

InnoDB也支撑通过特定的语句停止显示锁定(储备引擎层):

select ... lock in share mode //同享锁 select ... for update //排他锁

MySQL Server层的显示锁定:

lock table和unlock table

(更多阅读:MySQL锁总结)

MySQL对分布式事务的支撑

分布式事务的实现方式有许多,既可以采纳innoDB供给的原生的事务支撑,也可以采纳新闻队列来实现分布式事务的终究一致性。这里我们主要聊一下innoDB对分布式事务的支撑。

MySQL 从 5.0.3 开端支撑分布式事务,当前分布式事务只支撑 InnoDB 储备引擎。一个分布式事务会触及多个动作,这些动作本身是事务性的。所有动作都必需一起成功完成,或者一起被回滚。

如图,mysql的分布式事务模型。模型中分三块:利用程序(AP)、资源治理器(RM)、事务治理器(TM):

  • 利用程序:定义了事务的边界,指定需要做哪些事务;
  • 资源治理器:供给了拜访事务的办法,平常一个数据库就是一个资源治理器;
  • 事务治理器:调和参与了全局事务中的各个事务。

分布式事务采纳两段式提交(two-phase commit)的方式:

  • 第一阶段所有的事务节点开端预备,告诉事务治理器ready。
  • 第二阶段事务治理器告诉每个节点是commit还是rollback。假如有一个节点失败,就需要全局的节点全部rollback,以此保证事务的原子性。

分布式事务(XA 事务)的 SQL 语法主要包罗:

XA {START|BEGIN} xid [JOIN|RESUME]

虽然 MySQL 支撑分布式事务,但是在测试历程中,还是发明存在一些问题:
假如分支事务在到达 prepare 状态时,数据库非常从新启动,效劳重视新启动今后,可以连续对分支事务停止提交或者回滚得操纵,但是提交的事务没有写 binlog,存在必然的隐患,大概致使使用 binlog 复原丧失部分数据。假如存在复制的数据库,则有大概致使主从数据库的数据不一致。

假如分支事务在施行到 prepare 状态时,数据库非常,且不克不及再正常启动,需要使用备份和 binlog 来复原数据,那么那些在 prepare 状态的分支事务由于并没有记载到 binlog,所以不克不及通过 binlog 停止复原,在数据库复原后,将丧失这部分的数据。

假如分支事务的客户端连接非常中止,那么数据库会主动回滚未完成的分支事务,假如此时分支事务已经施行到 prepare 状态, 那么这个分布式事务的其他分支大概已经成功提交,假如这个分支回滚,大概致使分布式事务的不完全,丧失部分分支事务的内容。
总之, MySQL 的分布式事务还存在比力严峻的缺陷, 在数据库或者利用非常的状况下,
大概会致使分布式事务的不完全。假如利用关于数据的完全性要求不是很高,则可以思考使
用。假如利用对事务的完全性有比力高的要求,那么关于当前的版本,则不引荐使用分布式
事务。

以上就是总结数据库事务与 MySQL 事务的具体内容,更多请关注百分百源码网其它相关文章!

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有150人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板