事务

一、事务的介绍

事务:表示操作集合,不可分割,要么全部成功,要么全部失败

事务的开始取决于一个DML语句

事务的结束:

  1、正常的commit或者rollback

  2、自动提交,一般情况下进行关闭操作,效率太低

  3、用户关闭会话之后会自动提交事务

  4、系统崩溃或断电的时候会回滚事务

二、事务的四个特性(ACID)

1、原子性:一个操作集合(事务)要么全部成功,要么全部失败

2、一致性:保证数据的一致性,经过n多个操作之后,数据的状态不会改变(转账时总金额不会改变)

3、隔离性:各个事务之间不会产生影响。严格的隔离性会降低效率,某些情况下会降低隔离级别来提高效率

4、持久性:所有数据的修改都必须持久化到存储介质,不会因为程序的关闭而导致数据的丢失

  注意:数据库所有特性中都是为了保证数据的一致性

三、锁的机制

为了解决在并发访问的时候,数据不一致的问题,需要给数据加锁

加锁的同时需要考虑‘粒度’的问题:

  操作对象有:①数据库

        ②表

        ③行

  一般情况下,锁的粒度越小,效率越高,粒度越大,效率越低

三、事务的隔离级别

利用mysql数据库命令行进行模拟:

  ①开启两个命令窗口

  ②关闭事务自动提交:set autocommit = 0(select @@autocommit查看事务是否自动提交,1为开启,0为关闭)

  注意:autocommit在不考虑隔离级别的时候主要针对增删改操作,不针对表创建

     在一个事务中创建表,即使没有commit,另一个事务中也可以找到对应表名

  ③准备测试数据

    创建数据库:create database tran;

    切换数据库(两个窗口都执行):use tran;

    创建表:create table psn(id int primary key,name varchar(10)) engine=innodb;

    插入数据:insert into psn values(1,'zhangsan');

    insert into psn values(2,'lisi');

    insert into psn values(3,'wangwu');

    commit;

1、读未提交:会造成脏读

  A:set session transaction isolation level read uncommitted.

       设置当前会话    事务       隔离      级别  读未提交

    start transaction;  开启一项新的事务

 

  B:set session transaction isolation level read uncommitted.

   start transaction; 

       A:select * from psn;

  B:select * from psn;  这时两个窗口数据一致

  A:update psn set name = 'x'

  A:select * from psn;  发现数据已经修改

  B:select * from psn;  发现数据已经修改,但此时A窗口中事务未提交

解释:A事务并未提交事务,但此时B窗口已经读到未提交的事务

2、读已提交:会造成不可重复读

  A:set session transaction isolation level read committed.

       设置当前会话    事务       隔离      级别  读已提交

    start transaction;  开启一项新的事务

  B:set session transaction isolation level read committed.

   start transaction; 

       A:select * from psn;

  B:select * from psn;  这时两个窗口数据一致

  A:update psn set name = 'y' where id = 1;  此时A窗口中数据发生改变

  B:select * from psn;  此时B窗口中数据未发生改变,屏蔽了脏读的情况

  A:commit;

  B:select * from psn;  此时数据已经改变

解释:在B窗口内,出现了情况不相同的两种数据情况。

   相当于你去银行取钱,在插卡的时间内,10点显示你的余额有1000,10点05分显示你的余额有500,在这期间你的银行卡是未拔出的。这是不合理的。

  若此时B窗口在提交事务后进行查询,则会显示正常数据。

3、可重复读:会造成幻读,只在插入和删除的时候会产生

  A:set session transaction isolation level repeatable read;

       设置当前会话    事务       隔离      级别    可重复读

    start transaction;  开启一项新的事务

  B:set session transaction isolation level repeatable read;

   start transaction; 

       A:select * from psn;

  B:select * from psn;  这时两个窗口数据一致

  A:update psn set name = 'y' where id = 2;  此时A窗口中数据发生改变

   commit;

  B:select * from psn;  此时B窗口中数据未发生改变,屏蔽了不可重复读的情况

   commit;

  A:start transation;

  B:start transation;

  A:select * from psn;

  B:select * from psn;  此时数据一致性

  A:insert into psn values(4,'e');

   commit;

  B:select * from psn;  发现无id为4的数据

  B:insert into psn values(4,'e');  在B窗口中执行A窗口中的插入语句,报错主键重复

解释:在B窗口中执行A窗口中的插入语句,报错主键重复,说明此时B窗口中已经查到id为4的数据,但未显示

4、序列化

原文地址:https://www.cnblogs.com/lyc-code/p/13508429.html