精华内容
下载资源
问答
  • 串行化和反串行化

    2020-12-22 03:26:16
    串行化是指存储和获取磁盘文件、内存或其他地方中的对象。在串行化时,所有的实例数据都保存到存储介质上, 在取消串行化时,对象会被还原,且不能与其原实例区别开来。只需给类添加Serializable属性,就可以实现...
  • 什么时候使用串行化? 在网络中传输对象的时候 向数据库中保存文件的时候 今天我们要提到四个函数 全部串行化 1.serialize(对象名) 将指定的类对象串行化 $str=serialize($per) //将per对象串行化,结果返回给$str ...
  • NULL 博文链接:https://zhycaf.iteye.com/blog/982092
  • PHP中串行化用法示例

    2020-12-19 21:24:18
    功能:串行化用于对对象的存储或者传输,通过反串行化得到这个对象。 1. Person.class.php: <?php /* 作者 : shyhero */ class Person{ //声明一个Person类 public $age; private $name; protected $sex; ...
  • 什么是可串行化MVCC

    万次阅读 2020-11-25 18:27:23
    所以数据库管理系统(Database Management System,DBMS)必须提供并发控制机制,使得并发的事务在冲突的时候被串行化执行。这种调度称为可串行化调度。 通过时间戳的调度规则通过比较时间戳来判定读写请求是否被...

    MVCC介绍

     MVCC, 即multi-version concurrency control,多版本并发控制。 它的核心思想是为每一个写操作创建一个新版本,不同的事务根据它的时间戳读取对应的版本。
     与锁机制相比,MVCC不阻塞读操作,也不阻塞写操作。很大程度上提高了事务的并发数,然后,可串行化的MVCC却可能会付出很大的回滚开销。

    可串行化MVCC

    1. 假设并行事务的所有操作都是非冲突操作,如果某个事务的操作导致了冲突,则该事务需回滚;
    2. 事务时间戳顺序(从低到高)即是事务冲突可串行化的顺序,如果事务的并行操作产生了冲突,则至少一个事务需要回滚重启;
    3. 每个记录都有多个已提交版本和多个零时版本,每个版本都包含读时间戳RT,写时间戳WT,和一个提交位C,提交位表示最近一次修改是否修改被提交。

     如下图所示;每次合法的写操作都将产生该记录的一个临时版本,读时间戳为创建该版本的事务的时间戳
    在这里插入图片描述
     时间戳产生的方式主要有以下两种

    1. 采用系统时间作为时间戳,只要确保调度器不会在一个时钟周期内调度两个以上的事务的;
    2. 采用计数器,单调递增,作为事务的逻辑时间戳

    导致冲突的两种操作

     在基于时间戳的调度中,同样也需要确保,事务最后的执行顺序必须是事务串行化的顺序。然而基于时间戳还是存在冲突。

    1. 过晚的读
      两个并行事务T,U,T比U先开始
      T:RT(X)
      U:WU(X)
      如果在U在T读之前写,则T的读就导致了一个冲突,使T,U无法通过非冲突交换等价于一个串行调度(T,U)。
      在这里插入图片描述
    2. 过晚的写
       两个并行事务T,U,T比U先开始
      T:WT(X)
      U:RU(X)
      T,U的串行调度为:WT(X),RU(X)
       如图所示,实际调度是:RU(X),WT(X),这个调度不能通过非冲突交换等价与串行调度(T,U),因此T的写操作导致了一个冲突,T该被回滚并重启。
      在这里插入图片描述

    可串行化多版本时间戳调度规则

     对于事务T的读写请求,按照如下规则进行调度

    假设收到事务T的读请求RT(X)

     该读请求会试图读取写时间戳小于或等于TS(T)的最大写时间戳的版本V,即写时间戳小于或等于T的版本中,离TS(T)最近的版本,找到这样的版本后V,直接读取;当成功读取一个版本的时候,如果TS(T)大于该版本的读时间戳,则设置其读时间戳为TS(T),否则不改变该版本读时间戳。这种不阻塞读的策略,会导致级联回滚,即一个事务回滚,会导致语气相关的事务跟着回滚。并且,同一个事务的double-write可能会导致该事务回滚。这里也可以采取读阻塞,直到该版本C位变为真。

    假设收到事务T的写请求WT(X)

    调度器首先找到写时间戳小于或等于TS(T)的所有版本中写时间戳最大的版本V(该版本可能未提交),如果V的读时间戳满足:RT(X) < TS(T),则创建一个新版本,置该版本写时间戳为TS(T)(此时还没有其他事务来读取该版本,可将该版本的读时间戳设置为T时间戳,因为不会有时间戳比T小的事务来读取该版本,这样做是合理的);如果V的写时间戳等于T的时间戳,即版本V是由T创建的,则直在版本V上修改即可;如果V的读时间戳不满足要求,则回中止T,并重启。

    假设收到事务的提交请求

     要求必须按照事务时间戳的顺序创建每个对象的提交版本,因此,如果一个事务提交时,在时间戳排序上,还有在它之前的事务未提交,该事务需要等待。

    假设收到事务的中止请求

     当一个事务被中止时,它创建的所有版本都需要被删除,因为读阻塞在这些版本上的事务需要重新开始读操作。如果有其他事务读取了该事务创建的版本,那么这些事务也需要重启。

    Read Committed隔离级别

     该隔离级别下,事务的读请求,每次读取的数据都是在该读请求发起时,是已提交的最新版本。
    对于事务T的读写请求,按照如下规则进行调度

    1. 假设收到事务T的读请求RT(X)
      该请求会读取在该请求发起的时刻,最近提交的事务创建的版本,即符合条件的版本是在该请求发起时,最新的已提交版本;
    2. 假设收到事务T的写请求WT(X)
      调度器首先找到写时间戳小于或等于TS(T)的所有版本中写时间戳最大的版本V(该版本可能未提交),如果V的读时间戳满足:RT(X) < TS(T),则创建一个新版本,置该版本写时间戳为TS(T)(此时还没有其他事务来读取该版本,可将该版本的读时间戳设置为T时间戳,因为不会有时间戳比T小的事务来读取该版本,这样做是合理的);如果V的写时间戳等于T的时间戳,即版本V是由T创建的,则直在版本V上修改即可;如果V的读时间戳不满足要求,则回中止T,并重启。
    3. 假设收到事务的提交请求
      因为事务创建的版本在未提交之前是不会被其他事务读取的,并且事务只会读取已经提交的数据,因此,事务发出提交请求时,就一定可以提交。
    4. 假设收到事务的中止请求
      当一个事务被中止时,它创建的所有版本都需要被删除,因为读阻塞在这些版本上的事务需要重新开始读操作。

    Repeatable Read 隔离级别

     该隔离级别下,事务的读请求,每次读取的数据都是在该事务开始之前,最近提交的数据。
     对于事务T的读写请求,按照如下规则进行调度

    1. 假设收到事务T的读请求RT(X)
      该请求会读取在该事务开始时,最近提交的事务创建的版本。记事务T的时间戳A(事务T开始的时刻),则版本列表中写时间戳(创建该版本的时间戳)小于等于A的所有已提交版本中写时间戳最大者即为符合条件的版本,即所读取的版本首先必须是已经提交了的,其次,它是离A最近的事务创建的版本;
    2. 假设收到事务T的写请求WT(X)
      调度器首先找到写时间戳小于或等于TS(T)的所有版本中写时间戳最大的版本V(该版本可能未提交),如果V的读时间戳满足:RT(X) < TS(T),则创建一个新版本,置该版本写时间戳为TS(T)(此时还没有其他事务来读取该版本,可将该版本的读时间戳设置为T时间戳,因为不会有时间戳比T小的事务来读取该版本,这样做是合理的);如果V的写时间戳等于T的时间戳,即版本V是由T创建的,则直在版本V上修改即可;如果V的读时间戳不满足要求,则回中止T,并重启。
    3. 假设收到事务的提交请求
      因为事务创建的版本在未提交之前是不会被其他事务读取的,并且,事务读取的数据都是在事务开始时已经提交的数据,因此,事务发出提交请求时,就一定可以提交。
    4. 假设收到事务的中止请求
      当一个事务被中止时,它创建的所有版本都需要被删除,因为读阻塞在这些版本上的事务需要重新开始读操作。

     按照上述规则可能出现一种不是幻读的错误,因此,它不是严格的RR隔离级别,可以参考postgreSQL的RR隔离级别,举例说明如下。
    事务T1,T2,表Table1,Table1中有一个整形字段Val。
    假设Table1中已经有2条记录,值分别为10,20,如下表所示:

    int idint val
    110
    220

    T1,T2的操作如下:
     T1读取第2行数据,设该行数据为X,则修改第一行数据为X;
     T2读取第1行数据,设该行数据为Y,修改第2行数据为Y;

     T1,T2的操作序列是为了将两行数据设置成相等的值,如果按照串行的执行顺序,最终2行将会是一样的值,但在Repeatable Read隔离级别下,由于读取限制,最后修改完成后,不能得到预期的效果。
     T1,T2的操作序列如下:
    在这里插入图片描述
     按照上述操作序列,在RR隔离级别下,最后第1行记录值为20,第2行记录值为10,这与串行执行的效果是不一致的。
     上述错误是postgreSQL在第三种隔离级别下的一个Bug,postgreSQL使用predicate lock修复了这个Bug,并将具有predicate lock的Reapeatable Read隔离级别作为第四种隔离级别。

    可串行化调度规则举例

    1. 使用多版本时间戳的调度规则,读操作永远不会被拒绝,因为过晚的读操作可以读更早的版本。
    2. 写操作被拒绝举例
      在这里插入图片描述
       上图有两个写时间戳为T1和T2的提交版本。
       操作序列为:
       T3 read; T3 write; T5 read; T4 write;
      a) T3请求一个读操作,它在T2版本上设置读时间戳T3。
      b) T3请求一个写操作,生成一个写时间戳为T3的临时版本。
      c) T5请求一个读操作,它访问写时间戳为T3的版本(小于T5的具有最高写时间戳的版本),同时设置该临时版本的读时间戳为T5。
      d) T4请求一个写操作,由于写时间戳为T3的版本的读时间戳T5大于T4,该写操作被拒绝。(如果该写操作不被拒绝,那么新版本的写时间戳将是T4。如果允许创建这个版本,那么这回合T5的读操作冲突,此时,T5的读操作应该使用时间戳为T4的版本。)
    1. 某个事务double-write导致回滚
      事务Ta,Tb,Tia< Tb(即Ta比Tb早开始)
      操作序列为:Ta write;Tb read;Ta write;
      在这里插入图片描述
      a) Ta请求一个写操作,生成一个写时间戳为Ta的临时版本;
      b) Tb请求一个读操作,它访问写时间戳为Ta的版本,该临时版本是写时间戳比Tb小的所有版本中写时间戳最大者,同时设置该版本读时间戳为Tb;
      c) Ta再次请求一个写操作,它会访问自己先前创建的版本,但是,该版本的读时间戳Tb > Ta,该写被拒绝,Ta回滚,并以一个更大的时间戳重启。
    展开全文
  • VC 文件串行化示例.rar

    2019-07-10 11:39:39
    VC 文件串行化示例,源代码下载,涉及到的知识点:C语言对文件读写的支持,FILE指针;文本文件和二进制文件的区别。用文本方式读写文件和以二进制方式读写文件的注意事项。C 对文件读写的支持,ofstream和ifstream的...
  • 串行化 图像显示 串行化 图像显示VC++图像编程小软件作业编程参考
  • 并行程序串行化执行

    2016-01-09 22:45:23
    使用CGLIB实现并行执行,博客地址:http://blog.csdn.net/yangzl2008/article/details/50489583
  • 升级RPC-client内部的连接池,在service连接选取上做微小改动,就能够实现“id串行化”,实现不同类型的业务gid/uid等的串行化、序列号需求
  • 把对象串行化 有时候需要把一个对象在网络上传输,为了方便传输,可以把整个对象转化为二进制串, 等到达另一端时,再还原为原来的对象,这个过程称之为串行化,就像我们现在想把一辆汽 车通过轮船运到美国去,因为...
  • java-串行化

    千次阅读 2018-11-07 09:53:51
    对象串行化 对象的寿命通常随着生成该对象的程序的终止而终止。有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复。我们把对象的这种能记录自己的状态以便将来再生的能力。叫作对象的持续性(persistence...

    人生在世,还不是有时笑笑人家,有时给人家笑笑

    对象串行化

    • 对象的寿命通常随着生成该对象的程序的终止而终止。有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复。我们把对象的这种能记录自己的状态以便将来再生的能力。叫作对象的持续性(persistence)。
    • 对象通过写出描述自己状态的数值来记录自己,这个过程叫对象的串行化(Serialization)。也就是说能够将对象进行存档。
    • 串行化的主要任务是写出对象实例变量的数值。如果变量是另一对象的引用,则引用的对象也要串行化。
    • 串行化可以使得对象成为永久性,对象在创建它的程序外仍能够存在和起作用,被存储的对象中包含了可在程序中恢复的信息。

    什么时候需要串行化?

    • 当你想把的内存中的对象状态(也就是实例变量,不是方法)保存到一个文件中或者数据库中时候。
    • 当你想用套接字在网络上传送对象的时候。
    • 当你想通过RMI传输对象的时候;

    串行化注意事项

    • 序列化时,只能保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量,而且串行化保存的只是变量的值,对于变量的任何修饰符,都不能保存。
    • 当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
    • 当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
    • 创建串行化对象时,要考虑是否保存该对象的所有实例变量,如果需要将某个实例变量排除在串行化中,可以使用限定符transient。是否串行某个实例变量需要考虑:
      (1) 安全方面的原因 :比如一个对象拥有private,public等变量在序列化进行传输的过程中,这个对象的private等域是不受保护的。如果对象中存储了敏感信息(如对某个资源访问的密码),将密码串行化到文件中将把它置于危险的境地。
      (2) 资源分配方面的原因:对于有些实例变量,每当恢复对象时都需要重新创建,例如引用文件或者输入流的对象,每次从对象流中读取被串行化的对象时,对于其中的引用文件或输入流的对象都必须重新创建。还有例如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现。
      (3) :考虑存储变量占用的空间的问题:如果变量的值无需通过串行化就可以确定,则不应对其进行串行化。

    如何实现串行化和

    • 在java.io包中,接口Serializable用来作为实现对象串行化的工具 ,只有实现了Serializable的类的对象才可以被串行化。它不包含任何必须实现的方法,Serializable的唯一用处就是指出类的对象可以以串行化的方式被存储和检索。
    • 要串行化一个对象,必须与一定的对象输入/输出流联系起来,通过对象输出流(ObjectOutputStream)将对象状态保存下来,再通过对象输入流(ObjectInputStream)将对象状态恢复。
    • 串行化将数据分解成字节流,以便存储在文件中或在网络上传输。反串行化就是打开字节流并重构对象。对象串行化化不仅要将基本数据类型转换成字节 表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例。

    对象串行化实现步骤

    1、定义一个可串行化对象

    package SerializableDemo;
    
    import java.io.Serializable;
    
    public class serializableDemo {
    
    	public static void main(String[] args) {
    		
    	}
    
    }
    
    class Hero implements Serializable{
    	/**
    	 * 这是一个可串行化的对象
    	 */
    	
    	//是自动生成的唯一标识
    	private static final long serialVersionUID = 1L;
    	
    	//对象属性
    	private String nickName;
    	private transient String password;//该变量为暂存变量,不被串行化。
    	int level;
    
    	//构造函数
    	public Hero(){
    		
    	}
    	public Hero(String nickName,String password,int level){
    		 this.nickName = nickName;
    		 this.password = password;
    		 this.level=level;
    	}
    	
    	//setter和getter
    	public String getNickName() {
    		return nickName;
    	}
    	public void setNickName(String nickName) {
    		this.nickName = nickName;
    	}
    	public String getPassword() {
    		return password;
    	}
    	public void setPassword(String password) {
    		this.password = password;
    	}
    	public int getLevel() {
    		return level;
    	}
    	public void setLevel(int level) {
    		this.level = level;
    	}
    }
    

    2、创建输出流,讲对象写入到文件中

    public class serializableDemo {
    
    	static String filePath = "C:/Users/asus-pc/Desktop/javaProject/Demo/src/SerializableDemo/myHero.dat";
    	private static OutputStream ops = null;
    	private static ObjectOutputStream objectOutputStream = null;
    	private static  Hero myHero  = null;
    	public static void main(String[] args) {
        	//要写入到文件中的对象
    		myHero = new Hero("fight", "753951", 15);
    		try {
    			//创建对象输出流
    			ops = new FileOutputStream(filePath);
    			objectOutputStream = new ObjectOutputStream(ops);
    			//将对象写入文件
    			objectOutputStream.writeObject(myHero);
    			System.out.println("写入成功");
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		
    	}
    
    }
    

    3、将对象反串行化到程序中

    	//将对象从文件中读出来
    			System.out.println("成功读出");
    			ips = new FileInputStream(filePath);
    			objectInputStream =new ObjectInputStream(ips);
    			 Hero readHero = (Hero) objectInputStream.readObject();
    			 //由于密码被transient限制,所以没有写入到文件中,也无法读出
    			 System.out.println("readHero的昵称:"+readHero.getNickName()+"\n密码:"+readHero.getPassword()+"\n级别"+readHero.getLevel());
    	
    
    

    运行结果
    写入成功
    成功读出
    readHero的昵称:fight
    密码:null
    级别15

    
    

    全部程序代码

    package SerializableDemo;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.OutputStream;
    import java.io.Serializable;
    
    public class serializableDemo {
    
    	static String filePath = "C:/Users/asus-pc/Desktop/javaProject/Demo/src/SerializableDemo/myHero.dat";
    	private static OutputStream ops = null;
    	private static ObjectOutputStream objectOutputStream = null;
    	private static  Hero myHero  = null;
    
    	private static InputStream ips =null;
    	private static ObjectInputStream objectInputStream = null;
    	public static void main(String[] args) {
    		myHero = new Hero("fight", "753951", 15);
    		try {
    			//创建对象输出流
    			ops = new FileOutputStream(filePath);
    			objectOutputStream = new ObjectOutputStream(ops);
    			
    			//将对象写入文件
    			objectOutputStream.writeObject(myHero);
    			System.out.println("写入成功");
    			
    			//将对象从文件中读出来
    			System.out.println("成功读出");
    			ips = new FileInputStream(filePath);
    			objectInputStream =new ObjectInputStream(ips);
    			 Hero readHero = (Hero) objectInputStream.readObject();
    			 //由于密码被transient限制,所以没有写入到文件中,也无法读出
    			 System.out.println("readHero的昵称:"+readHero.getNickName()+"\n密码:"+readHero.getPassword()+"\n级别"+readHero.getLevel());
    	
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		}
    		
    	}
    
    }
    
    class Hero implements Serializable{
    	/**
    	 * 这是一个可串行化的对象
    	 */
    	
    	//是自动生成的唯一标识
    	private static final long serialVersionUID = 1L;
    	
    	//对象属性
    	private String nickName;
    	private transient String password;//该变量为暂存变量,不被串行化。
    	int level;
    
    	//构造函数
    	public Hero(){
    		
    	}
    	public Hero(String nickName,String password,int level){
    		 this.nickName = nickName;
    		 this.password = password;
    		 this.level=level;
    	}
    	
    	//setter和getter
    	public String getNickName() {
    		return nickName;
    	}
    	public void setNickName(String nickName) {
    		this.nickName = nickName;
    	}
    	public String getPassword() {
    		return password;
    	}
    	public void setPassword(String password) {
    		this.password = password;
    	}
    	public int getLevel() {
    		return level;
    	}
    	public void setLevel(int level) {
    		this.level = level;
    	}
    }
    

    串行化对象和字节数组的转换

    通过ByteArrayInputStream和ByteArrayOutputStream可以将串行化的对象和字节数组进行转化

    package testDemo;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.util.Date;
    
    public class testDemo  {
    	
    	public byte[] objectToBytes(Object obj){
    		  byte bytes[] =null;
    		   ByteArrayOutputStream bArrayOutputStream =new ByteArrayOutputStream();
    		   try {
    			ObjectOutputStream objectOutputStream =new ObjectOutputStream(bArrayOutputStream);
    		   objectOutputStream.writeObject(obj);
    		   bytes =bArrayOutputStream.toByteArray();
    		   
    		   } catch (IOException e) {
    			e.printStackTrace();
    		}
    		   return bytes;
    	}
    	public Object bytesToObject(byte bytes[]){
    		  ByteArrayInputStream bArrayInputStream =new ByteArrayInputStream(bytes);
    	      Object obj =null;
    		  try {
    			  ObjectInputStream objectInputStream =new ObjectInputStream(bArrayInputStream);
    	          obj =objectInputStream.readObject();
    		  } catch (IOException e) {
    			e.printStackTrace();
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		}
    		return obj;  
    	}
    	
    	public static void main(String[] args) {
    		testDemo myTestDemo =new testDemo();
    		byte b[] =myTestDemo.objectToBytes(new Date()); 
    		//将日期这个对象转换成字节数组
    		System.out.println(myTestDemo.bytesToObject(b));
    		//将转换成的数组转换成对象,输出
    	}
    	
    }
    
    

    运行结果

    Mon Nov 19 21:19:19 CST 2018
    
    
    展开全文
  • 可串行性与“严格”可串行化区别 多年来,“可串行化/序列化”(serializability)被称为数据库隔离级别的“ 黄金标准 ”。它是绝大多数商业数据库系统中提供的最高隔离级别,一些高度广泛部署的系统甚至无法提供...

    可串行性与“严格”可串行化区别

    多年来,“可串行化/序列化”(serializability)被称为数据库隔离级别的“ 黄金标准 ”。它是绝大多数商业数据库系统中提供的最高隔离级别,一些高度广泛部署的系统甚至无法提供隔离级别与可序列化一样高。

    在这篇文章中,我们展示了可序列化的可行性,并且说明它从未成为数据库系统的“黄金标准”。事实上,严格的可串行化才一直是黄金标准。正如我们将看到的,因为在遗留数据库系统中实现可串行化提供了关键的严格保证,所以“可串行化”和“严格可串行化”之间的区别大多被忽略了。然而,在以云为中心的分布式系统的现代世界中,这种差异是显著的。

    这篇文章首先解释了数据库系统中隔离的概念,然后说明了这两个隔离级别之间的重要差异,以及应用程序员需要注意的“仅仅”引入可串行化系统导致的正确性bug。

    背景:什么是“隔离”

    假设我们有一个售票应用程序,允许人们购买限量供应活动的门票。应用程序将以下形式的事务发送到数据存储(当客户尝试买票时):

    如果库存> 0那么
         库存=库存-1; 
         过程(顺序)
         返回成功
    否则 
         返回失败FAIL
    

    如果数据存储支持ACID事务,则将以原子方式处理上述代码: 将处理整个订单并减少库存,或者订单与库存两者都不处理。要么全部处理要么全部失败,除此以外其他任何事情都不可能发生。

    如果系统中只运行一个事务,则显然运行上述代码不会出现任何问题。如果库存足够,则会处理订单。否则,它不会。

    问题通常仅在并发下发生:多个客户尝试同时购买一张票。如果有更多客户试图购买门票而不是库存,理想的最终结果是所有库存都将被出售,而不是更多。

    如果允许上述代码在没有系统级保证的情况下运行,则代码中存在明显的“竞争条件”。两个并行线程可以同时运行第一行,并且都看到库存为“1”。因此,两个线程都通过IF条件并处理订单,这导致库存超卖的负面结果。

    系统级保证在面对并发请求时防止这些负面结果属于ACID的I - “隔离”。

    隔离的黄金标准是“可串行化serializability”。保证可串行化的系统能够同时处理事务,但保证最终结果等同于单独处理每个事务时发生的事情,一个接一个地处理(串行就好像没有并发)。这是一个非常强大的保证,它能够经受住时间的考验(50年),从而能够在其上构建健壮且无错误的应用程序。

    可串行化隔离如此强大的原因是应用程序开发人员根本不需要推理并发性。开发人员只需单独地关注单个事务的逻辑正确性即可。只要每个单独的事务不能违反应用程序的语义,开发人员就可以确保同时运行其中许多事务也不会违反应用程序的语义。在我们的示例中,我们只需要确保上面显示的6行代码的正确性。只要在数据库的任何启动状态下处理它们时它们都是正确的,那么应用程序在并发时将保持正确。

    可串行化的脏数据秘密:它看起来并不像“安全”

    尽管具有令人难以置信的可串行化能力,但确实存在更强的保证,并且保证“仅仅”依靠可串行化的数据库实际上容易出现与并发性相关的其他类型的错误。

    可串行化的第一个限制是:它不限制如何选择等效的事务序列顺序。指定一组并发执行的事务,系统保证它们将被等效地处理为串行顺序,但它不保证任何特定的串行顺序。

    结果,指定一组相同的并发事务处理的两个副本可能最终处于非常不同的最终状态,因为他们选择以不同的等效序列顺序处理事务。因此,“仅仅”依靠可序列化的数据库的复制不能只复制输入并让每个复制事务进程同时处理输入就可以了,这不能保证复制。

    相反,一个复制的进程必须首先处理工作负载,然后处理来自原初始进程发生的一系列状态改变的复制,这个状态改变的复制是原初始进程通过网络发布的,因此,数据经过网络延迟到达时间和原始进程中原始数据发生的时间有滞后性。

    可串行化的第二个限制是:可序列化系统选择的等同序列顺序不必与提交给系统的事务的顺序相关,。在“事务X之后提交的事务Y“与“Y在在X之前处理”是符合等效序列顺序的。

    即使在X完成后的几周内提交了Y,这也是正确的 , 理论上可以为可串行化系统带来Y及时返回,并在X存在之前处理系统状态(只要没有提交的事务读取Y写入的相同数据),从技术上讲每个只读事务都可以返回空集(即数据库的初始状态),并且不会违反串行化保证,这是合法的,因为系统可以使只读事务“及时”返回,并在写入数据B的任何事务之前以串行顺序获得一个卡位。

    任何用户都不太可能使用始终为每个只读查询返回空集的数据库。那么可串行化如何成为“黄金标准”?

    在过去,数据库只能在一台机器上运行。因此,数据库系统保证隔离级别保证更强一致性要超过可串行化serializability。事实上,以至于多年来没有人为这个强大的隔离保证保证(即使几乎每个数据库系统都保证它)。隔离级别最终被Herlihy和Wing命名为: 严格可串行化。

    严格的可串行性更安全

    严格的可串行化在普通可串行化之上添加了一个简单的额外约束。如果事务Y在事务X完成后启动(请注意,这意味着X和Y根据定义不是并发的),那么保证严格可串行化的系统保证:

    (1)最终状态等同于按顺序处理事务和

    (2)X必须在该序列顺序中的Y之前。

    因此,如果我要向保证严格可串行化的系统提交事务,我知道该事务的任何读取都将反映由于已提交的事务(至少)到达我的事务处理时的数据库的状态。提交。事务可能看不到同时提交的事务的写入,但至少它会看到在它开始之前完成的所有写入。

    当数据库位于一台机器上时,保证严格的可串行化通常不会增加相对于普通可串行化的工作量。在进行交易之前,每个现有系统(一个例外是Daniel Abadi博士的2014年“懒惰交易”论文)必须执行该交易事务中涉及的写入。对于稍后出现的事务,忽略这些写入(而不是看到它们)通常比看到它们更多的工作。因此,几乎每个在一台机器上运行的可序列化系统也保证了严格的可串行化。这导致了行业现状,数据库系统的文档表明它们保证了“可串行性”,但实际上,它们保证了“严格的可串行性”。

    “严格的可串行化”保证消除了系统返回我们在上一节中讨论过的陈旧/空数据的可能性。[但是,它没有消除我们在该部分讨论过的副本分歧问题。我们将在以后的帖子中回到这个问题。]

    总结到目前为止:实际上,“严格可串行化”是数据库系统中的黄金标准隔离级别。但是,只要大多数数据库在一台机器上运行,在保证“可串行化”的系统和保证“严格可串行化”的系统中没有可察觉的差异。因此,通俗地说,“可串行化”被称为黄金标准,这种口语化的语义不准确性从未如此重要。

    分布式系统使可串行性变得危险

    在分布式系统中,从可串行化到严格可串行化的跳跃不再是微不足道的。

    以我们的售票应用程序的简单示例为例:

    假设票证库存在两台机器上复制 --A和B ----两者都允许处理交易。客户向机器A发出减少库存的事务。此事务完成后,将向计算机B发出另一个事务,以读取当前库存。在一台机器上,第二个事务肯定会读取第一个事务的写入。但是现在他们在不同的机器上运行,如果系统不能保证一致的读取跨机器,第二个事务很可能会返回一个陈旧的脏值(例如,如果复制是异步的,并且第一个事务的写入尚未从A复制到B,则可能会发生这种情况)。这种陈旧的读取不会违反可串行化。它相当于第一个事务之前的第二个事务的序列顺序。但是,由于第二次交易事务是在第一次交易完成后提交的,因此肯定违反了严格的可串行性。

    因此,当跨机器复制数据时,可串行化和严格的可串行化之间存在巨大而实际的差异。在选择要使用的数据库系统之前,最终用户必须意识到这种差异。无法保证严格可序列化的分布式系统容易出现许多不同类型的错误。​​​​​​​

    可序列化和严格可序列化之间的区别远远超过我之前示例中的“陈旧读取”错误。让我们看看可能出现的另一个错误,称为“因果反转”。

    如果您存入的金额(在您的所有账户中)超过5000美元,银行会“free checking免费检查”。爱丽丝正好5000美元,需要给孩子的保姆签发支票,所以她将一些额外的钱转入她的储蓄账户。在确认转移成功并且钱存入她的储蓄账户后,她从她的支票账户中提取支票。当她看大结果时,她发现因为没有在5000美元以上的账户中保持平衡而受到的处罚。

    所以发生了什么事?违反严格的可串行性。两个交易—她的储蓄账户的增加和她的支票账户的扣除被重新排序,以便在储蓄账户添加之前发生支票账户扣除,即在加法完成之后提交减法。在仅保证普通可串行化的系统中,这种重新排序是完全可能的,但在保证严格可串行化的系统中是不可能的。在这种类型的示例中,这种事务重新排序是非常常见的,其中如果不相交的数据位于分布式系统中的不同机器上,则事务访问不相交的数据(检查余额与储蓄余额)。交易事务重新排序后,Alice在两个账户的余额暂时低于5000美元,这导致了处罚。如果银行在一个保证严格可串行化的系统之上构建他们的应用程序,他们将不必处理来自Alice的愤怒投诉电话。

    转自

    揭露数据库隔离级别的肮脏秘密:可串行性与“严格”可串行化区别! - Matt Freels

    展开全文
  • 串行化是把每个对象转化为二进制字符串。 <?php class Person { var $name; var $sex; var $age; function __construct($name = "", $sex = "男", $age = 22) { $this->name = $name; $this->sex = $sex; ...
  • 为了用串行化流程控制让几个异步任务按顺序执行,需要先把这些任务按预期的执行顺序放到一个数组中,这个数组将起到队列的作用:完成一个任务后按顺序从数组中取出下一个。 数组中的每个任务都是一个函数。任务完成...
  • 对象序列化 串行化

    2015-03-31 09:52:44
    对象序列化 串行化 实现java对象的保存
  •  | = PHP5研究中心: http://blog.csdn.net/haohappy2004 +——————————————————————————-+ */ 第十三节–对象串行化 串行化可以把变量包括对象,转化成连续bytes数据. 你可以将
  • 1.pickle对象串行化 pickle模块实现了一个算法可以将任意的Python对象转换为一系列字节。这个过程也被称为串行化对象。可以传输或存储表示对象的字节流,然后再重新构造来创建有相同性质的新对象。 1.1 编码和解码...
  • 串行化 冲突可串行化 判断方法

    千次阅读 多人点赞 2020-04-13 01:25:00
    串行化调度 多个事务从宏观上看是并行执行的,但其微观上是并行执行的 可串行性:串行肯定是正确的,执行结果等价于串行调度 且 结果也正确的调度 == 可串行化调度 冲突可串行性:交换2个 没有冲突的操作 最终...

    这篇博文,视频、笔记,主要参考中国大学mooc,战老师。

    B站:https://www.bilibili.com/video/BV1PJ411F78b ,视频编号P234附近,有相关知识点

    这篇文章,冲突的判定那里 写的比较好

    可串行化调度

    多个事务运行,从宏观上是串行执行的,但其微观上是交错运行的。

    可串行性:可串行化的调度对数据库状态的影响,与某个串行序列对数据库状态的影响 一致。

    (执行结果等价于串行调度 且 结果也正确的调度 == 可串行化调度)

    冲突可串行性:交换2个 没有冲突的操作 最终变成 串行调度

     

    注意:满足冲突可串行性,一定满足 可串行性!可串行性 不一定满足 冲突可串行性

    读写 与 冲突

    冲突:

    事务相同(下标相同:一个在写,一个在读   【对于同一个事物一读一写不能互换,因为程序员规定的】

    处理对象相同(操作对象),一读一写、写写   【对于同一个对象一读一写,两写  都不能互换】

    有向无环图,拓扑算法检验.

    展开全文
  • 还有不满足冲突可串行化条件的可串行化调度,称为目标可串行化(view serializability)的调度。 有3个事务, L1和L2是目标等价的(view equivalence): T1=W1(Y)W1(X) T2=W2(Y)W2(X), T3=W3(X) 调度L1=W1(Y)...
  • MFC的文件串行化操作

    2010-09-03 21:00:35
    在MFC中使用文档类提供的串行化类进行文件的写入以及读取,保存图形的一些特征(比如起点和终点、画笔和画刷的类型)并进行图形的重绘。
  • 本篇博客,Alice为大家介绍的是Hadoop中作为首选串行化系统的Avro。 文章目录简介特点Avro数据类型和模式Avro基本类型Avro复杂类型Avro数据序列化/反序列化方法1 使用编译的方式序列化反序列化方法2 不使用编译的...
  • 关系的度(degree)一对一与一对多并发控制并发控制概述封锁三协议第一封锁协议第二封锁协议第三封锁协议活死锁死锁预防一次封锁(完全封锁)顺序封锁死锁诊超时法等待图法死锁解除并发调度的可串行性可串行化调度...
  • 串行化调度

    千次阅读 2020-05-13 15:30:17
    如果一个调度的结果与某一串行调度执行的结果等价,则称该调度是可串行化调度,否则是不可串调度。 冲突可串行化调度 如果调度中一对连续操作是冲突的,则意味着如果它们的执行顺序交换,则至少i改变其中一个事务的...
  • VS2010工程 我们能都知道单文档多文档串行化非常简单,因为框架已经为我们生成好了. 但是单文档串行化这方面,资料还真是少.
  • 事务可串行化原理

    千次阅读 2019-05-23 23:12:26
    【冲突可串行化】:若调度 S 与一个串行调度等价,则称 S 是冲突可串行化。 例如,A = 100,B = 10。 冲突可串行化调度是可串行化调度的充分条件 ,换言之,若一个调度是冲突可串行化,则一定是可串行化调度。...
  • 数据串行化

    2019-01-08 05:08:38
    利用CArchive类实现数据串行化, 需要注意的是, 串行化的对象一定要是从CObject类派生出来的, 同时, 要在被串行化的对象的类的头文件中进行宏定义   //文件串行化宏定义 DECLARE_SERIAL(CMyBox)   ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 224,248
精华内容 89,699
关键字:

串行化