Mysql中的事务

来源:互联网 发布:mysql access 对比 编辑:程序博客网 时间:2024/06/06 20:20

事务的定义:

事物就是一组数据库操作的集合

事物的特性:

A:atomic原子性:一个事务里面的所有操作要么全部完成,要么全部失败,回滚到事物执行前的状态
C:Consistent一致性:事务前后数据库的完整性必须保持一致
I:Isolation隔离性:一个事务的执行的不会被其它事务的执行影响,多个并发的事务之间相互隔离,互不影响
D:Durability永久性:一旦一个事务提交后,其对数据库的改变就是永久的

事物的隔离性的影响

  • 脏读:事务A读取到事务B未提交的数据
  • 不可重复读:事务A两次读取的数据不一致(事物B执行了update)
  • 虚读(幻读):事务A两次读取的数据不一致(事物B执行了insert)
  • 丢失更新:两个事务对同一个数据进行更新,后提交的事务,将先提交的事务的修改的数据覆盖了

事物没有隔离性产生的问题的解决

设置事物的隔离级别
1. read uncommited:不能解决任何隔离性产生的问题
2. read commited:可以避免脏读
3. repeatable read:可以避免脏读和不可重复读,不可避免虚读
4. serializable :可以避免任何问题(串行化)

实验

mysql默认的情况下,是自动提交事务:

show variables like '%commit%'+--------------------------------+-------+| Variable_name                  | Value |+--------------------------------+-------+| autocommit                     | ON    || innodb_commit_concurrency      | 0     || innodb_flush_log_at_trx_commit | 1     |+--------------------------------+-------+更改mysql数据库为手动事务set autocommit = false

读脏数据(事务A读取到事务B的未提交的数据)

事物A:

+----+------+-------+| id | name | money |+----+------+-------+|  1 | aaa  |  1010 ||  2 | bbb  |  1000 ||  3 | ccc  |  1000 |+----+------+-------+//A窗口的事物:set session transaction isolation level read committed;start transaction;update account set money = money + 10 where id = 1;//B窗口set session transaction isolation level read committed;start transaction;select * from account;得到的结果是:+----+------+-------+| id | name | money |+----+------+-------+|  1 | aaa  |  1000 ||  2 | bbb  |  1000 ||  3 | ccc  |  1000 |+----+------+-------+A:执行commitB:select * from account;//得到的结果为:+----+------+-------+| id | name | money |+----+------+-------+|  1 | aaa  |  1010 ||  2 | bbb  |  1000 ||  3 | ccc  |  1000 |+----+------+-------+证明read committed确实解决了读脏数据的错误,但是又带来了另一个问题,即B两次读取同一个数据的时候,出现了不一致的情况。
repetable readA事务:set session transaction isolation level repeatable readstart transactionupdate account set money = money + 100 where id = 1;B事务:set session transaction isolation level repeatable readstart transactionselect * from account;+----+------+-------+| id | name | money |+----+------+-------+|  1 | aaa  |  1000 ||  2 | bbb  |  1000 ||  3 | ccc  |  1000 |+----+------+-------+事物A:commit;事务B:select * from account;+----+------+-------+| id | name | money |+----+------+-------+|  1 | aaa  |  1000 ||  2 | bbb  |  1000 ||  3 | ccc  |  1000 |+----+------+-------+证明得到的结果是一样的,那么repeatable read这个隔离级别是可以避免脏数据和不可重复读的

解决丢失更新

丢失更新的产生的情况
这里写图片描述

解决方案

悲观锁 (假设丢失更新一定会发生 ) —– 利用数据库内部锁机制,管理事务提供的锁机制(不需要我们进行任何的操作,数据库内部会帮我们维护)
1.共享锁
select * from table lock in share mode(读锁、共享锁)
2.排它锁
select * from table for update (写锁、排它锁)
update语句默认添加排它锁

乐观锁 (假设丢失更新不会发生)——- 采用程序中添加版本字段解决丢失更新问题

create table product (     id int,     name varchar(20),     updatetime timestamp);insert into product values(1,'冰箱',null);update product set name='洗衣机' where id = 1;

解决丢失更新:在数据表添加版本字段,每次修改过记录后,版本字段都会更新,如果读取是版本字段,与修改时版本字段不一致,说明别人进行修改过数据 (重改)
这里写图片描述

原创粉丝点击