事务

事务

MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!

在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
事务用来管理 insert,update,delete 语句

事务的特征

数据库事务具有ACID这4个特性:

  • A:Atomic,原子性,将所有SQL作为原子工作单元执行,要么全部执行,要么全部不执行;

  • C:Consistent,一致性,事务完成后,所有数据的状态都是一致的,即A账户只要减去了100,B账户则必定加上了100;

  • I:Isolation,隔离性,如果有多个事务并发执行,每个事务作出的修改必须与其他事务隔离;

  • D:Duration,持久性,即事务完成后,对数据库数据的修改被持久化存储。

MYSQL 事务处理主要有两种方法:

1、用 BEGIN, ROLLBACK, COMMIT来实现

BEGIN 开始一个事务
ROLLBACK 事务回滚
COMMIT 事务确认
2、直接用 SET 来改变 MySQL 的自动提交模式:

SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交
事务开始于:
连接到数据库上,并执行一条DML语句(insert/update/delete)
前一个事务结束后,又输入了另外一条DML语句
事务结束于:
执行commit/rollback
执行一条DDL语句,自动commit
执行一条DCL语句,自动commit
断开与数据库的连接
执行了一条DML语句,该语句却失败了;在这种情况中,会为这个DML语句执行Rollback语句
在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交

begin;    启动事务,否则默认单语句单事务
update t_clz set stu_num=100 where id=4;   可以执行多条sql语句【针对增删改DML】
savepoint bb;   定义存储点,可以执行部分回滚
update t_clz set stu_num=55 where id=1;   可以是多条sql语句
rollback to bb;  撤销存储点bb之后的所有操作,但是bb之前的操作仍旧存在
commit; 提交所有操作结果,注意没有部门提交的概念

JDBC中事务编程实现

在这里插入图片描述
第二条sql语句出错会导致语句1执行无效

事务并发操作中会有4种非正常情况,分别是脏读、幻读、不可重复读和丢失更新(2类)。可以通过隔离等级以限制并发操作的程度。对应不同的事务隔离等级有4种,隔离等级越高,出现的问题越少,但是并发性越差。一般是采用默认【数据库隔离等级+Java编程补偿】方法解决并发的问题

第一种隔离级别:Read uncommitted(读未提交)
如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据,该隔离级别可以通过“排他写锁”,但是不排斥读线程实现。这样就避免了更新丢失,却可能出现脏读,也就是说事务B读取到了事务A未提交的数据
解决了更新丢失,但还是可能会出现脏读

第二种隔离级别:Read committed(读提交)
如果是一个读事务(线程),则允许其他事务读写,如果是写事务将会禁止其他事务访问该行数据,该隔离级别避免了脏读,但是可能出现不可重复读。事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
解决了更新丢失和脏读问题

第三种隔离级别:Repeatable read(可重复读取)
可重复读取是指在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务(包括了读写),这样避免了不可重复读和脏读,但是有时可能会出现幻读。(读取数据的事务)可以通过“共享读镜”和“排他写锁”实现。
解决了更新丢失、脏读、不可重复读、但是还会出现幻读

第四种隔离级别:Serializable(可序化)
提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行,如果仅仅通过“行级锁”是无法实现序列化的,必须通过其他机制保证新插入的数据不会被执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读
解决了更新丢失、脏读、不可重复读、幻读(虚读)

在这里插入图片描述
MySQL默认隔离等级为可重复读
批处理batch
灵活指定SQL语句中的变量PreparedStatement
对存储过程中进行调用CallableStatement
运用事务处理Transaction
批处理Batch

conn.setAutoCommit(false); //设为手动提交 
stmt = conn.createStatement(); 
for (int i = 0; i < 200; i++) { 	
           stmt.addBatch("insert into t_user (userName,pwd,regTime) values ('hao" + i + "', '666666',now())"); 
} 
stmt.executeBatch(); 
conn.commit(); //提交事务

总结

索引总结
(1)数据库索引用于加速查询;
(2)虽然哈希索引是O(1),树索引是O(log(n)),但SQL有很多有序需求,故数据库使用树型索引;
(3)InnoDB不支持手动创建哈希索引;
(4)数据预读的思路是:磁盘读写并不是按需读取,而是按页预读,一次会读一页的数据,每次加载更多的数据,以便未来减少磁盘IO
(5)局部性原理:软件设计要尽量遵循“数据读取集中”与“使用到一个数据,大概率会使用其附近的数据”,这样磁盘预读能充分提高磁盘IO
(5)数据库的索引最常用B+树:
很适合磁盘存储,能够充分利用局部性原理,磁盘预读
很低的树高度,能够存储大量数据
索引本身占用的内存很小
能够很好的支持单点查询,范围查询,有序性查询;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值