精华内容
下载资源
问答
  • Java中的Serializable接口和事务中的事务隔离级别Serializable,虽说单词一样,但它们之间基本没关系. Java中的Serializable接口是实现一个内存对象保存成磁盘文件并从磁盘文件恢复成内存对象的机制. 事务隔离级别...

    Java中的Serializable接口和事务中的事务隔离级别Serializable,虽说单词一样,但它们之间基本没关系.

    Java中的Serializable接口是实现一个内存对象保存成磁盘文件并从磁盘文件恢复成内存对象的机制. 

    1、比如比较常见的地方:在hibernate或者mybatis中实体类都要实现一个serializable这个接口,这样实现一个内存对象保存磁盘。并且这个是一个以流的方式,一个对象的流输出流—》字节输出流—》磁盘(简单的描述);

    2、还有一个地方就是在实现克隆的时候:当一个类实现了serializable接口,然后对这个对象进行克隆的时候就是深克隆。机制就是对象写到一个对象输出流—》字节输出流—》字节的输入流—》对象输入流(然后从对象输入流中拿一个对象)就完成了克隆;这样的这个过程中吧对象写到流里的过程是序列化(Serilization)过程,而把对象从流中读出来的过程则叫做反序列化(Deserialization)过程。写在流里是对象的一个拷贝。然后原对象任然存在JVM里面;

    事务隔离级别Serializable是实现多个访问共享数据的事务得以线性顺序进行机制的.

    展开全文
  • Serializable是最严格的隔离级别。 在Serializable隔离级别下,所有事务按照次序依次执行,因此,脏读、不可重复读、幻读都不会出现。 虽然Serializable隔离级别下的事务具有最高的安全性,但是,由于事务是...

    1. Serializable

    Serializable是最严格的隔离级别。

     

    在Serializable隔离级别下,所有事务按照次序依次执行,因此,脏读、不可重复读、幻读都不会出现。

     

    虽然Serializable隔离级别下的事务具有最高的安全性,但是,由于事务是串行执行,所以效率会大大下降,应用程序的性能会急剧降低。

    如果没有特别重要的情景,一般都不会使用Serializable隔离级别。

     

    2. 数据库的默认隔离级别

    如果没有指定隔离级别,数据库就会使用默认的隔离级别。

    在MySQL中,如果使用InnoDB,默认的隔离级别是Repeatable Read

     

     

     

     

    https://www.liaoxuefeng.com/wiki/1177760294764384/1245268341158240

    展开全文
  • 事务隔离级别Serializable Isolation Level

    千次阅读 2016-10-18 11:30:39
    In the serialization isolation level, a transaction sees only changes committed at the time the transaction—not the query—began and changes made by the transaction ... A serializable transaction o
    In the serialization isolation level, a transaction sees only changes committed at the time the transaction—not the query—began and changes made by the transaction itself. A serializable transaction operates in an environment that makes it appear as if no other
     users were modifying data in the database.
    --事务只能看见提交点时事务的变化,就像一个单用户环境一样

    Serializable isolation is suitable for environments: --适用条件
    • With large databases and short transactions that update only a few rows   --很短的事务
    • Where the chance that two concurrent transactions will modify the same rows is relatively low  --一般没有人修改相同的数据
    • Where relatively long-running transactions are primarily read only  --相对长时间运行的事务为只读


    **注意:SERIALIZABLE并不意味所有事物都能表现的好像是以一种串行方式一个接一个执行。

    --以下实验以T0为时间顺序递延

    EODA@PROD1> create table a( x int);
    
    Table created.
    
    EODA@PROD1> create table b( x int);
    
    Table created.
    
    EODA@PROD1> alter session set isolation_level = serializable;  --T1会话1
    
    Session altered.
    
    EODA@PROD1> alter session set isolation_level = serializable;  --T2会话2
    
    Session altered.
    
    EODA@PROD1> insert into a select count(*) from b;  --T3会话1
    
    1 row created.
    
    EODA@PROD1> insert into b select count(*) from a;  --T4会话2
    
    1 row created.
    
    EODA@PROD1> commit;  --T5会话1
    
    Commit complete.
    
    
    EODA@PROD1> commit;  --T6会话2
    
    Commit complete.
    
    EODA@PROD1> select * from a;
    
    	 X
    ----------
    	 0
    
    EODA@PROD1> select * from b;
    
    	 X
    ----------
    	 0


    如果是串行化完成操作那么表b行值就应该是1,但是实验结果显示都是0。因为我们count函数记数都是在T1时间。

    展开全文
  • 文章目录2、Read committed(读提交)...设置MySQL的事务隔离级别为REPEATABLE-READ 在my.ini配置文件最后加上如下配置,然后在服务中重启MySQL服务 [mysqld] transaction-isolation = SERIALIZABLE 查询当前的事务...

    2、Read committed(读提交)

    可以避免脏读,但可能出现不可重复读和幻读。

    设置MySQL的事务隔离级别为REPEATABLE-READ
    在my.ini配置文件最后加上如下配置,然后在服务中重启MySQL服务

    [mysqld]
    transaction-isolation = SERIALIZABLE
    

    查询当前的事务隔离级别
    在这里插入图片描述

    脏读

    场景:公司发工资了,领导把5000元打到Tom的账号上,但是该事务并未提交,而Tom正好去查看账户,发现工资已经到账,账户多了5000元,非常高兴,可是不幸的是,领导发现发给Tom的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,Tom再次查看账户时发现账户只多了2000元。

    create table account(
    	id int(36) primary key comment '主键',
    	card_id varchar(16) unique comment '卡号',
    	name varchar(8) not null comment '姓名',
    	balance float(10,2) default 0 comment '余额'
    )engine=innodb;
    # 插入数据
    insert into account (id,card_id,name,balance) values (1,'6226090219290000','Tom',1000);
    

    结果
    在这里插入图片描述
    老板类

    import java.sql.*;
    public class Boss {
    	public static void main(String[] args) {
    		Connection connection = null;
    		Statement statement = null;
    		try {
    			Class.forName("com.mysql.jdbc.Driver");
    			String url = "jdbc:mysql://127.0.0.1:3306/test";
    			connection = DriverManager.getConnection(url, "root", "root");
    			connection.setAutoCommit(false);
    			statement = connection.createStatement();
    			String sql = "update account set balance=balance+5000 where card_id='6226090219290000'";
    			statement.executeUpdate(sql);
    			Thread.sleep(30000);//30秒后发现工资发错了
    			connection.rollback();
    			sql = "update account set balance=balance+2000 where card_id='6226090219290000'";
    			statement.executeUpdate(sql);
    			connection.commit();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			//释放资源
    				try {
    					if(statement != null) { 
    						statement.close();
    					}
    				} catch (SQLException e) {
    					e.printStackTrace();
    				}
    				try {
    					if(connection != null) {
    						connection.close();
    					}
    				} catch (SQLException e) {
    					e.printStackTrace();
    				}
    		}
    	}
    }
    

    员工类

    import java.sql.*;
    public class Employee {
    	public static void main(String[] args) {
    		Connection connection = null;
    		Statement statement = null;
    		ResultSet resultSet = null;
    		try {
    			Class.forName("com.mysql.jdbc.Driver");
    			String url = "jdbc:mysql://127.0.0.1:3306/test";
    			connection = DriverManager.getConnection(url, "root", "root");
    			statement = connection.createStatement();
    			String sql = "select balance from account where card_id='6226090219290000'";
    			resultSet = statement.executeQuery(sql);
    			if(resultSet.next()) {
    				System.out.println(resultSet.getDouble("balance"));
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			//释放资源
    		try {
    				if(resultSet != null) { 
    				resultSet.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    			
    			try {
    				if(statement != null) { 
    					statement.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    			try {
    				if(connection != null) {
    					connection.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    执行Boss类主方法之后,再执行Employee主方法
    在这里插入图片描述
    当Boss类主方法执行完之后,再一次执行Employee主方法
    在这里插入图片描述
    并没有出现脏读的情况,所以当事务的隔离级别为SERIALIZABLE的时候可以避免脏读

    不可重复读

    场景:Tom拿着工资卡去消费,酒足饭饱后在收银台买单,服务员告诉他本次消费1000元,Tom将银行卡给服务员,服务员将银行卡插入POS机,POS机读到卡里余额为3000元,就在Tom磨磨蹭蹭输入密码时,他老婆以把Tom工资卡的3000元转到自己账户并提交了事务,当Tom输完密码并点击“确认”按钮后,POS机检查到Tom的工资卡已经没有钱,扣款失败。

    创建表

    # 建表
    create table account(
    	id int(36) primary key comment '主键',
      card_id varchar(16) unique comment '卡号',
      name varchar(8) not null comment '姓名',
      balance float(10,2) default 0 comment '余额'
    )engine=innodb;
    # 插入数据
    insert into account (id,card_id,name,balance) values (1,'6226090219290000','Tom',3000);
    insert into account (id,card_id,name,balance) values (2,'6226090219299999','LilY',0);
    

    在这里插入图片描述
    机器类

    import java.sql.*;
    public class Machine {
    	public static void main(String[] args) {
    		Connection connection = null;
    		Statement statement = null;
    		ResultSet resultSet = null;
    		try {
    			double sum=1000;//消费金额
    			Class.forName("com.mysql.jdbc.Driver");
    			String url = "jdbc:mysql://127.0.0.1:3306/test";
    			connection = DriverManager.getConnection(url, "root", "root");
    			connection.setAutoCommit(false);
    			statement = connection.createStatement();
    			String sql = "select balance from account where card_id='6226090219290000'";
    			resultSet = statement.executeQuery(sql);
    			if(resultSet.next()) {
    				System.out.println("余额:"+resultSet.getDouble("balance"));
    			}
    			System.out.println("请输入支付密码:");
    			Thread.sleep(1000);//1秒后密码输入成功
    			resultSet = statement.executeQuery(sql);
    			if(resultSet.next()) {
    				double balance = resultSet.getDouble("balance");
    				System.out.println("余额:"+balance);
    				if(balance<sum) {
    					System.out.println("余额不足,扣款失败!");
    					return;
    				}
    			}
    			sql = "update account set balance=balance-"+sum+" where card_id='6226090219290000'";
    			statement.executeUpdate(sql);
    			connection.commit();
    			System.out.println("扣款成功!");
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			//释放资源
    			try {
    				if(resultSet != null) { 
    				resultSet.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    			try {
    				if(statement != null) { 
    					statement.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    			try {
    				if(connection != null) {
    					connection.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    妻子类

    import java.sql.*;
    public class Wife {
    	public static void main(String[] args) {
    		Connection connection = null;
    		Statement statement = null;
    		try {
    			double money=3000;//转账金额
    			Class.forName("com.mysql.jdbc.Driver");
    			String url = "jdbc:mysql://127.0.0.1:3306/test";
    			connection = DriverManager.getConnection(url, "root", "root");
    			connection.setAutoCommit(false);
    			statement = connection.createStatement();
    			String sql = "update account set balance=balance-"+money+" where card_id='6226090219290000'";
    			statement.executeUpdate(sql);
    			sql = "update account set balance=balance+"+money+" where card_id='6226090219299999'";
    			statement.executeUpdate(sql);
    			connection.commit();
    			System.out.println("转账成功");
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			//释放资源
    			try {
    				if(statement != null) { 
    					statement.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    			try {
    				if(connection != null) {
    					connection.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    先运行Machine类的主函数,
    在这里插入图片描述
    再运行Wife类的主函数
    在这里插入图片描述
    30秒之后Machine类主函数显示余额不足
    在这里插入图片描述
    查看数据库
    在这里插入图片描述
    上面的结果显示并没有出现不可重复读,所有当事务的隔离级别设置为SERIALIZABLE的时候可以避免不可重复读,妻子转账成功了,Tom也成功的支付了费用,但是卡中只有3000元,查看数据库中的数据,任然为Tom的余额为负数,所以这里序列化可以避免不可重复的问题,但是并没解决重复读,读取快照的问题

    幻读

    场景:Tom的老婆工作在银行部门,她时常通过银行内部系统查看Tom的工资卡消费记录。她查询到Tom当月工资卡的总消费额(select sum(amount) from record where card_id=‘6226090219290000’ and date_format(create_time,’%Y-%m’)=‘2019-05’)为80元,而Tom此时正好在外面收银台买单,消费1000元,即新增了一条1000元的消费记录并提交了事务,老婆又查询了Tom当月工资卡消费明细(select amount from record where card_id=‘6226090219290000’ and date_format(create_time,’%Y-%m’)=‘2019-05’),可查出的结果竟然发现有一笔1000元的消费。

    建表

    create table account(
    	id int(36) primary key comment '主键',
      	card_id varchar(16) unique comment '卡号',
      	name varchar(8) not null comment '姓名',
      	balance float(10,2) default 0 comment '余额'
    )engine=innodb;
    insert into account (id,card_id,name,balance) values (1,'6226090219290000','Tom',3000);
    
    create table record(
    	id int(36) primary key comment '主键',
        card_id varchar(16) comment '卡号',
        amount float(10,2) comment '金额',
        create_time date comment '消费时间'
    )engine=innodb;
    insert into record (id,card_id,amount,create_time) values (1,'6226090219290000',37,'2019-05-01');
    insert into record (id,card_id,amount,create_time) values (2,'6226090219290000',43,'2019-05-07');
    

    在这里插入图片描述
    银行类

    import java.sql.*;
    public class Bank {
    	public static void main(String[] args) {
    		Connection connection = null;
    		Statement statement = null;
    		ResultSet resultSet = null;
    		try {
    			Class.forName("com.mysql.jdbc.Driver");
    			String url = "jdbc:mysql://127.0.0.1:3306/test";
    			connection = DriverManager.getConnection(url, "root", "root");
    			connection.setAutoCommit(false);
    			statement = connection.createStatement();
    			String sql = "select sum(amount) total from record where card_id='6226090219290000' and date_format(create_time,'%Y-%m')='2019-05'";
    			resultSet = statement.executeQuery(sql);
    			if(resultSet.next()) {
    				System.out.println("总额:"+resultSet.getDouble("total"));
    			}
    			Thread.sleep(30000);//30秒后查询2019年5月消费明细
    			sql="select amount from record where card_id='6226090219290000' and date_format(create_time,'%Y-%m')='2019-05'";
    			resultSet = statement.executeQuery(sql);
    			System.out.println("消费明细:");
    			while(resultSet.next()) {
    				double amount = resultSet.getDouble("amount");
    				System.out.println(amount);
    			}
    			connection.commit();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			//释放资源
    			try {
    				if(resultSet != null) { 
    				resultSet.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    			
    			try {
    				if(statement != null) { 
    					statement.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    			try {
    				if(connection != null) {
    					connection.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    丈夫类

    import java.sql.*;
    public class Husband {
    	public static void main(String[] args) {
    		Connection connection = null;
    		Statement statement = null;
    		try {
    			double sum=1000;//消费金额
    			Class.forName("com.mysql.jdbc.Driver");
    			String url = "jdbc:mysql://127.0.0.1:3306/test";
    			connection = DriverManager.getConnection(url, "root", "root");
    			connection.setAutoCommit(false);
    			statement = connection.createStatement();
    			String sql = "update account set balance=balance-"+sum+" where card_id='6226090219290000'";
    			statement.executeUpdate(sql);
    			sql = "insert into record (id,card_id,amount,create_time) values (3,'6226090219290000',"+sum+",'2019-05-19');";
    			statement.executeUpdate(sql);
    			connection.commit();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			//释放资源	
    			try {
    				if(statement != null) { 
    					statement.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    			try {
    				if(connection != null) {
    					connection.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    执行Bank类的主函数,查询结果为80
    在这里插入图片描述
    执行Husband类的主函数,执行之后主方法并不会停止等待Bank类的主方法执行结束之后才结束

    Bank类的主函数结束,本月消费明细
    在这里插入图片描述
    查询数据库
    在这里插入图片描述
    上述的场景,并没有出现幻读的情况,所以把数据库的事务隔离级别设置为SERIALIZABLE的时候可以避免幻读的问题,但是这样效率就会大打折扣。

    展开全文
  • 错误出错提示和数据库以及代码都在下面。 ![图片说明](https://img-ask.csdn.net/upload/201804/28/1524874692_109467.jpg) ![图片说明]...!...!...我测试的方法是200个进程同一时刻访问
  • 因此通过设置会话1的隔离级别isolation_level=serializable,避免了其他会话的修改丢失。 理论上serializable还能避免幻影读,但是幻影读不太好实现。 SQL标准中定义了4中IO隔离级别 READ Uncommited READ ...
  • 7.事务隔离级别Serializable

    千次阅读 2018-03-20 12:51:14
    最后我们学习一下最高的事务隔离级别Serializable,顾名思义,可串行化的,也即并发事务串行执行。很显然,该级别可以避免前面讲到的所有问题:“脏读”、“不可重复读”和“幻读”。代价是处理事务的吞吐量低,严重...
  • 数据库隔离级别---MySQL的默认隔离级别就是Repeatable,Oracle默认Read committed,最高级别Serializable
  • 事务隔离级别——Serializable

    千次阅读 2019-06-10 16:57:44
    根据实际需求,通过设置数据库的事务隔离级别可以解决多个事务并发情况下出现的脏读、不可重复读和幻读问题,数据库事务隔离级别由低到高依次为Read uncommitted、Read committed、Repeatable read和Serializable等...
  • oracle事务隔离级别:SERIALIZABLE

    千次阅读 2017-11-29 22:53:25
    SERIALIZABLE 一般认为这是最受限的隔离级别,但是它也提供了最高程度的隔离性。...SERIALIZABLE这个隔离级别可以确保这两个查询总会返回相同的结果。其他事务的副作用对查询是不可见的,而不论这个查询
  • 首先,我们先设置MySQL事务隔离级别SERIALIZABLE 在my.ini配置文件最后加上如下配置 #可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE. [mysqld] transaction-isolation = ...
  • 左边的客户连接,先开始一个事务,右边的客户连接,后开始一个事务。...在Serializable隔离级别下,所有事务按照次序依次执行,因此,脏读、不可重复读、幻读这些数据不一致的情况都不会出现。 虽然Serializable...
  • The Serialization isolation level 是最严格的隔离级别。对所有提交的transactions, 这个level模仿了序列化的transaction执行; 就像并发的transaction是一个接着一个执行的,序列化地,而不是并发地。使用...
  • mysql SERIALIZABLE隔离级别死锁问题

    千次阅读 2018-10-13 13:52:28
    最近的项目,为了保障绝对的一致性,使用SERIALIZABLE作为隔离级别。 然后就爆出了很诡异的死锁。 报错log如下: org.springframework.dao.DeadlockLoserDataAccessException: PreparedStatementCallback; SQL ...
  • 比如A事务使用了 serializable 隔离级别,只查询数据,那么B事务这个时候如果要update相同数据,则必须等待A事务完成。 串行化事务中,读锁被获取后,写锁需要等待 代码演示1: // 设置当前事务级别,这种作用域为...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,149
精华内容 859
关键字:

隔离级别serializable