MySQL-浅析数据库事务

目录

事务概述

事务处理

事务隔离级别

概述

1.脏读

2.不可重复读

3. 幻读

4.串行化

总结


 事务概述

在数据库开发过程中,经常会为了完成某一功能而编写一组SQL语句。为了确保每一组SQL语句操作数据的完整性,MySQL引入了事务的管理。

事务处理机制在应用程序开发过程中有着非常重要的作用,它可以保证在同一个事务中的操作具有同步性,从而让整个应用程序更加安全。

举例:现实生活中,人们经常会进行转账操作,转账可以分为转入和转出两部分,只有这两个部分都完成才认为转账成功。在数据库中,转账过程中的SQL语句,只要任意一条语句出现异常没有执行成功,就会导致两个账户的转账金额不同步,出现转账错误。MySQL中可以使用事务避免上述情况的发生。

 事务处理

MySQL中,用户执行的每一条SQL语句,默认都会当成单独的事务自动提交。如果想要将一组SQL语句作为一个事务,需要在执行这组SQL语句之前显式地开启事务。

     显式开启事务的语句如下:

     START TRANSACTION;

  开启事务之后,后续的每一条SQL语句将不再自动提交,用户想要提交时,需要手动提交事务。只有事务提交后,事务中的SQL语句才会生效。

    手动提交事务的语句具体如下:

    COMMIT;

如果不想提交当前事务,还可以使用下列语句取消事务(即回滚),

    具体如下:

ROLLBACK;

需要注意的是,ROLLBACK语句只能针对未提交的事务执行回滚操作,已提交的事务是不能回滚的。当执行COMMIT或ROLLBACK后,当前事务就会自动结束。

事务隔离级别

概述

MySQL支持多线程并发访问,用户可以通过不同的线程执行不同的事务。为了保证多个事务之间互不影响,就需要为事务设置适当的隔离级别。

MySQL中,事务有4种隔离级别,分别为READ UNCOMMITTED(读未提交)、READ COMMITTED(读已提交)、REPEATABLE READ(可重复读)和SERIALIZABLE(串行化)。

MySQL的默认隔离级别是REPEATABLE READ(可重复读),

READ UNCOMMITTED是事务隔离级别中最低的级别,在该级别下的事务可以读取到其他事务中未提交的数据,这种读取方式也被称为脏读(Dirty Read)。

MySQL中READ COMMITTED级别下,事务只能读取其他事务已经提交的内容,可以避免脏读现象,但是会出现不可重复读和幻读的情况。不可重复读是指在事务内重复读取别的线程已经提交的数据,由于多次查询期间,其他事务做了更新操作,出现多次读取的结果不一致的现象。

从例子中理解事务隔离级别更容易

首先创建book表,并插入数据。

CREATE TABLE book (

id INT PRIMARY KEY AUTO_INCREMENT,

       name VARCHAR(20) NOT NULL UNIQUE,

       price DECIMAL(6,2) NOT NULL,

       upload_time  DATETIME NOT NULL,

       state CHAR(1) NOT NULL DEFAULT 0

);
insert into book ( name, price, upload_time, borrower_id, borrow_time, state) values ( "Java基础入门(第3版)", 59, now(), null, null, "0");

insert into book (name, price, upload_time, borrower_id, borrow_time, state) values ("三国演义",69,now(),null,null,"0");

insert into book (name, price, upload_time, borrower_id, borrow_time, state) values ("MySQL数据库入门",40,now(),"1","2021-08-06","1");

insert into book (name, price, upload_time, borrower_id, borrow_time, state) values ("JavaWeb程序开发入门",49,now(),null,null,"0");

insert into book (name, price, upload_time, borrower_id, borrow_time, state) values ("西游记",59,now(),null,null,"0");

insert into book (name, price, upload_time, borrower_id, borrow_time, state) values ("水浒传",66.66,now(),null,null,"0");

insert into book (name, price, upload_time, borrower_id, borrow_time, state) values ("唐诗三百首",39,now(),null,null,"0");

insert into book (name, price, upload_time, borrower_id, borrow_time, state) values ("Python数据可视化",49.8,now(),null,null,"0");

查询book表

select * from book;

1.脏读

 设置默认会话隔离级别为可重复读,并查询结果。

语句:

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

SELECT @@session.transaction_isolation;

更改默认会话隔离级别为读未提交,并查询结果。

语句:

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

SELECT @@session.transaction_isolation;

 

开启事务,并将前两本书更改名字。

语句:

start transaction;



update book set name="百年孤独" where name="Java基础入门(第3版)";

update book set name="欧也妮·葛朗台" where name="三国演义";

未提交事务前,在另外一个窗口使用查询语句,查到在事务中更改的数据,完成脏读。

语句:

select * from book;

回滚后使用查询语句,数据仍是开启事务前的数据。

语句:

ROLLBACK;

select * from book;

2.不可重复读

在另一个窗口即B窗口设置读已提交。

语句:

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

重复脏读开启事务、更改数据的步骤,查看数据。

在B端查看数据,此时没有显示在开启事务中更改的数据。

3. 幻读

A窗口设置可重复读,A、B窗口同时查询book表,查询记录相同,同时开启事务并

更新数据。

语句:

窗口A:

SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

select * from book;

start transaction;

update book set name = '百年孤独' where name = 'Java基础入门(第3版)';

update book set name = '老人与海' where name = '三国演义';

窗口B:

start transaction;

update book set name = '百年孤独' where name = 'Java基础入门(第3版)';

update book set name = '老人与海' where name = '三国演义';

A窗口提交事务前,B窗口修改数据,显示修改失败。

A窗口提交事务,并查询结果。

 B窗口不提交事务,同时查询结果。

 此时,数据仍是A窗口修改之前的数据。一个事务提交的数据,不能被其他事务读取到就是幻读。

4.串行化

A、B窗口开启串行化事务级别,同时开启事务。此时A窗口插入数据,B窗口再插入数据,显示等待,或等待超时,直到A窗口提交事务,B窗口才能执行插入操作。

语句:

A:

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

start transaction;

select * from book;

insert into book (name, price, upload_time, borrower_id, borrow_time, state) values ("基督山伯爵",60.9,now(),null,null,"0");

B:

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

start transaction;

insert into book (name, price, upload_time, borrower_id, borrow_time, state) values ("哈姆雷特",60.9,now(),null,null,"0");

假设把所有的事务都会按照固定顺序执行,执行完一个事务再继续执行下一个事务的写入操作,这意味着队列中同时只能执行一个事务的写入操作,这就是串行化。

总结

MySQL中,事务有4种隔离级别,分别为READ UNCOMMITTED(读未提交)、READ COMMITTED(读已提交)、REPEATABLE READ(可重复读)和SERIALIZABLE(串行化)。

READ UNCOMMITTED读未提交可能会出现脏读,READ COMMITTED读已提交避免了脏读问题,仍然可能出现不可重复读和幻读问题。REPEATABLE READ可重复读解决了不可重复读的问题,保证了事务内多次读取同一数据的结果是一致的,但仍然可能出现幻读问题。SERIALIZABLE是事务的最高隔离级别,虽然串行化能解决脏读、幻读、重复读的问题,但可能导致大量的超时和锁竞争的现象,因此也是性能最低的一种隔离级别。

  • 43
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
是的,我了解您的问题。MySQL是一种开源的关系型数据库管理系统,因其易用性和可靠性而备受欢迎。以下是一些关于MySQL数据库管理的常见问题和答案: 1. 如何创建一个MySQL数据库? 答:您可以使用MySQL命令行或者MySQL Workbench来创建一个新的数据库。在命令行中,您可以使用CREATE DATABASE语句来创建一个新的数据库。在MySQL Workbench中,您可以使用“Create a new Schema”向导来创建一个新的数据库。 2. 如何备份和恢复MySQL数据库? 答:您可以使用mysqldump命令来备份MySQL数据库,通过将备份文件导入到新的MySQL服务器中来恢复MySQL数据库。另外,您也可以使用MySQL Workbench的备份和恢复功能来备份和恢复MySQL数据库。 3. 如何优化MySQL数据库的性能? 答:您可以通过使用索引、优化查询、调整服务器参数和升级硬件等方式来优化MySQL数据库的性能。另外,您也可以使用MySQL Workbench的性能分析器来分析查询语句的性能,并查找潜在的性能问题。 4. 如何保护MySQL数据库的安全性? 答:您可以通过使用强密码、限制对MySQL服务器的访问、定期备份数据、更新MySQL服务器和应用程序等方式来保护MySQL数据库的安全性。另外,您也可以使用防火墙和安全软件来保护服务器免受网络攻击。 希望这些回答能够解决您的问题。如果您还有其他问题,请随时提出。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SmoothSailingT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值