zoukankan      html  css  js  c++  java
  • 事务 TRANSACTION

    事务是数据库中一个但单独的执行单元(Unit),他通常由高级数据库操作语言(如SQL)或编程语言(如C++、Java)编写的用户程序的执行所引起。当在数据库中更改数据成功时,在事务中更改的数据便会提交,不再改变;否则,事务就取消或者回滚,更改无效。

    事务必须满足四个属性:ACID

    原子性(Atomicity):事物是一个不可分割的整体,为了保证事务的总体目标,事务必须具有原子性,即当数据修改时,要么全部执行,要么全部都不执行,即不允许事务部分的完成,避免只执行这些操作的一部分而带来的错误。

    一致性(Consistency):如果事务出现错误,则回到最原始的状态。一个事务在执行之前和执行之后,数据库数据必须保持一致状态。由于并发操作带来的数据不一致性通常包括以下几种类型:丢失数据修改、“脏读”、不可重复读、“幻读”。

    隔离性(Isolation):多个事务之间无法访问,只有当事务完成后才可以得到结果。即当两个或多个事务并发执行时,为了保证数据的安全性,将一个事务内部的操作隔离起来,不被其它正在进行的事务看到。数据库有四种类型的事务隔离级别:未提交的读、提交的读、可重复的读、串行化。

    持久性(Durability):事务完成以后,DBMS保证它对数据库中数据的修改时永久性的。当一个系统崩溃时,一个事务依然可以提交,当事务完成后,操作结果保存在磁盘中,不会被回滚。持久性一般通过数据库备份与恢复来保证。

    严格而言,数据库事务属性都是由数据库管理系统来进行保证的,在整个应用程序的运行过程中,应用程序无需去考虑数据库的ACID实现。

    并发事务处理可能带来的问题

    备注:数据库中读数据的一些概念

    更新丢失(Lost Update):当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题——最后的更新覆盖其他事务所做的更新。

    “脏读”(Dirty reads):一个事务读取了另一个事务尚未提交的数据。就是当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交到的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。

    不可重复读(Non-Repeatable Reads):一个事务的操作导致另一个事务在事务内两次读取到不同的数据,这是由于查询时系统中其他事务修改的提交引起的。比如事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。即在一个事务内,多次读同一个数据,在这个事务还没有结束时,另一个事务也访问该同一数据。那么在第一个事务的两次读数据之间,由于第二个事务的修改,使得第一个事务读到的数据可能不一样,这样就发生了在一个事务内两次读到的数据是不一样的,因此成为不可重复读,即原始读取不可重复。

    “幻读”(Phantom Reads):一个事务的操作导致另一个事务前后两次查询的结果数据量不同。指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行;同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还没有修改的数据行,就如同发生的幻觉一样。

    不可重复读和幻读的区别是:

    不可重读读是指读到了已经提交的事务的更改数据(修改或者删除),即多次读一条记录,发现该记录中某些列值被修改过;防止不可重复读只需对操作的数据添加行级锁,防止操作中数据发生变化。

    “幻读”是指读到了其他已经提交的事务的新增数据。即多次读一个范围内的记录,发现结果集不一致(记录增多或者减少);防止“幻读”,往往需要添加表级锁,将整张表锁定,防止新增记录。

    事务的隔离级别

    数据库的事务隔离越严格,并发副作用越小,但付出的代价也越大,因为事务隔离实质上就是使事务在一定程度上“串行化”进行,这显然与“并发”是矛盾的。

    为了解决“隔离”和“并发”的矛盾,定义了4个事务隔离级别

     事务隔离级别 读数据一致性 脏读 不可重复读 幻读
    未提交读(Read uncommintted) 最低级别,只能保证不读取物理上损坏的数据
    已提交读(Read committed) 语句级
    可重复读(Repeatable read) 事务级
    可序列化(Serializable) 最高级别,事务级

    MySQL8.0默认的事务隔离级别是: 可重复读

    MySQL8.0中查看当前的事务隔离级别

    mysql> show variables like 'transaction_isolation';

    JDBC中的五种事务隔离级别

    为了解决与“多个线程请求相同数据”相关的问题,事务之间通常会用锁互相隔离开。大多数主流的数据库支持不同类型的锁。因此,JDBC

    API 支持不同类型的事务,他们由Connection对象指派或确定(Connection的5个静态常量)。

    ① TRANSACTION_NONE  // 不支持事务

    ② TRANSACTION_READ_UNCOMMITTED  // 未提交读。说明在提交前一个事务可以看到另一个事务的变化。此事务级别下,允许“脏读”、不可重复读、“幻读”

    ③ TRANSACTION_READ_COMMITTED  // 已提交读。说明读取未提交的数据是不允许的。此事务级别下,不允许“脏读”,但允许不可重复读、“幻读”

    ④ TRANSACTION_REPEATEABLE_READ  // 可重复读。说明事务保证能够再次读取相同的数据而不会失败。此事务级别下,不允许“脏读”、不可重复读,但允许“幻读”

    ⑤ TRANSACTION_SERIALIZABLE  // 可序列化,这是最高的事务级别。不允许“脏读”、不可重复读、“幻读”

    使用事务

    MySQL中,事务用来管理 INSERT、UPDATE、DELETE语句,不能回退 SELETE语句。

    默认情况下,事务是自动提交的。因此如果想要使用事务,必须先取消Connection的自动提交方式。

    SQL中通过 SET AUTOCOMMIT=0 来设置
    JDBC中通过调用 Connection的setAutoCommit(boolean) 方法来设置

    设置事务隔离级别

    SQL中使用 SET TRANSACTION 语句改变单个回话或者所有进程链接的隔离级别
    SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
    JDBC中通过Connection的setTransactionisolation(int level) 来设置。参数即Connection的5个静态常量。

    使用 START TRANSACTION 或者 BEGIN 语句开始一项新的事务。

    使用 COMMIT 和 ROLLBACK 来提交或者回滚事务

    使用 CHAIN 和 RELEASE 子句分别用来定义在事务提交或者回滚之后的操作。CHAIN会立即启动一个新的事务,并且和刚才的事务具有相同的隔离级别;RELEASE 则会断开和客户端的链接。

    一般情况下,通过执行COMMIT(提交)或ROLLBACK(回滚)语句来终止事务。当执行COMMIT语句时,自从事务启动以来对数据库所做的一切更改就成为永久的,即被写入磁盘,而当执行ROLLBACK语句时,自从事务启动以来对数据库所做的一切更改都会被撤销,并且数据库中内容返回到事务开始之前所处的状态。无论什么情况,在事务完成是,都能保证回到一致状态。

  • 相关阅读:
    centos 7 部署confluence
    在Ubuntu操作系统里安装Docker
    Python模块-pip
    微信小程序 等宽不等高瀑布流
    微信小程序 保存图片和复制文字 功能
    C# 模拟鼠标移动和点击
    使用Fiddler抓包工具更改请求的url请求参数
    C#中Request.ServerVariables详细说明及代理
    (C# webservice 获取客户端IP疑难杂症)---试过n种方法都失败,获取代理服务器,访问者客户端真实IP
    C# 命名管道中客户端访问服务器时,出现“对路径的访问被拒绝”
  • 原文地址:https://www.cnblogs.com/0820LL/p/9706341.html
Copyright © 2011-2022 走看看