MySQL事务处理

MySQL数据库事务全面解析

目录

1.基础概念

2.事务的特性(ACID)

3.隔离等级

4.事务并发问题

5.事务自动提交

1.自动提交模式

2.多语句使用事务

6.开启事务

1.事务解释

2.示例

参考资料


1.基础概念

什么是事务?

‌‌数据库事务(Transaction)是指访问并可能操作各种数据的一个数据库操作,该过程由多个步骤组成,要么全部成功,要么全部失败。

需要注意的是,MySQL数据库中只有InnoDB存储引擎支持事务。

2.事务的特性(ACID)

原子性(Atomicity):事务是最小操作单元,要么全部成功,要么全部失败。

一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。

隔离性(Isolation):数据库允许多个并发事务同时对数据进行读写、修改,提供的隔离机制,防止多个事务并发执行时由于交叉执行而导致数据的不一致

持久性(Durability):事务处理结束后,对数据的修改就是永久的

3.隔离等级

  • 读未提交(READ UNCOMMITTED):可以读取到事务未提交的数据,隔离性差。会出现【赃读】。
  • 读已提交(READ COMMITTED):可以读取到事务已提交的数据,隔离性一般。避免了【赃读】,但是会出现【不可重复读】、【幻读】。
  • 可重复读(REPEATABLE READ):InnoDB默认的隔离等级。同一事务中多次读取结果一致。解决了【不可重复读】,但可能导致【幻读】。
  • 可串行化(SERIALIZABLE):类似REPEATABLE READ。在可串行化并且禁用自动提交时,InnoDB隐式地将所有纯SELECT语句转换为SELECT ... LOCK IN SHARE MODE。我们知道这种情况下是只读,所以会造成阻塞,杜绝了并发造成的问题,相应的会效率低下。

备注:在我们开启事务时,自动提交(autocommit)会在会话被隐式禁用,直到使用commit/rollback结束事务。

4.事务并发问题

  • 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。
  • 不可重复读:事务 A 多次读取同一数据,事务 B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致
  • 幻读:A将数据表中所有数据改为状态2,但是B就在这个时候插入一条状态为1的记录,A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

小结:【不可重复读】和【幻读】很容易混淆,不可重复读侧重于修改幻读侧重于新增/删除

【幻读】的分析与解决,关注【怎么解决幻读?】

5.事务自动提交

1.自动提交模式

在InnoDB中,所有的用户活动都是发生在事务内部。如果启用了自动提交模式,则每个SQL语句都会单独形成一个事务。

自动提交模式查看

select @@autocommit;

2.多语句使用事务

  1. 关闭自动提交模式,由commit/rollback 结束事务。
  2. 【start transaction】开启事务,将autocommit发起的commit动作交由commit/rollback关键字手动控制。

看下面一组例子:

#准备一张新表article

#自动提交模式下,开启事务,插入一条数据”文章11”;

#手动关闭自动提交模式,插入”文章22”、”文章33”,删除”文章11”,rollback - 查看数据;

#手动关闭自动提交模式,插入”文章22”、”文章33”,删除”文章11”,commit - 查看数据;

补充:在我们开启事务时,autocommit会在会话被隐式禁用,直到使用commit/rollback结束事务。与我们手动设置效果大差不差。具体看【开启事务】

6.开启事务

1.事务解释

#开启事务

START TRANSACTION | BEGIN

.......

.......

#结束事务

COMMIT | ROLLBACK

  • START TRANSACTION开启事务
  • BEGIN开启事务
  • COMMIT:提交事务,执行变更
  • ROLLBACK:回滚事务,取消变更

默认情况下,MySQL是在autocommit开启的状态下运行。意味着每条SQL语句不在事务内部时,就像被START TRANSACTIONCOMMIT包裹一样。

而我们有多条语句,需要闭包执行,整个动作需要原子性时,可以使用事务来处理。START TRANSACTION语句在执行过程中,自动提交模式(autocommit)会隐式禁用,直到使用COMMITROLLBACK结束事务。

2.示例

#当前为自动提交模式,article表有两条数据。

#开启事务插入一条数据,并查看结果

参考资料

MySQL数据库锁定读取:The InnoDB Engine: Locking Reads

MySQL数据库事务隔离等级:The InnoDB Engine: Transaction Isolation Levels

MySQL数据库事务自动提交:The InnoDB Engine: autocommit,Commit,and Rollback

MySQL数据库事务开启:The InnoDB Engine: Start Transaction

关于mysql事务处理 public static void StartTransaction(Connection con, String[] sqls) throws Exception { if (sqls == null) { return; } Statement sm = null; try { // 事务开始 System.out.println("事务处理开始!"); con.setAutoCommit(false); // 设置连接不自动提交,即用该连接进行的操作都不更新到数据库 sm = con.createStatement(); // 创建Statement对象 //依次执行传入的SQL语句 for (int i = 0; i < sqls.length; i++) { sm.execute(sqls[i]);// 执行添加事物的语句 } System.out.println("提交事务处理!"); con.commit(); // 提交给数据库处理 System.out.println("事务处理结束!"); // 事务结束 //捕获执行SQL语句组中的异常 } catch (SQLException e) { try { System.out.println("事务执行失败,进行回滚!\n"); con.rollback(); // 若前面某条语句出现异常时,进行回滚,取消前面执行的所有操作 } catch (SQLException e1) { e1.printStackTrace(); } } finally { sm.close(); } } 通常都是上述的写法, 在mysql 不支持事务的时候 , 中间的 setAutoCommit 的事务操作是不是都不生效. 现在innoDB支持 事务了, 上述的 java 代码是否能实现 以下的 事务隔离的 操作, 在修改的时候处于锁定状态 或者 只可以通过存储过程来实现, 单行的锁定 BEGIN; SELECT book_number FROM book WHERE book_id = 123 FOR UPDATE; --这里for update , 以前用Oracle的时候也是有这个行锁 // ... UPDATE book SET book_number = book_number - 1 WHERE book_id = 123; COMMIT;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值