mysql事务介绍

mysql中,事务其实是一个最小的不可分割的工作单元,事务能够保证一个业务的完整性

比如:我们的银行转账:
    a -> -100
    update user set money=money-100 where name='a';
    
    b -> +100
    update user set money=money+100 where name='b';
    
---实际的程序中,如果只有一条语句成功了,而另外一条没有执行成功?
---出现数据前后不一致
---多条sql语句,可能会同时成功的要求,要么就同时失败。

1、mysql默认是开启事务的(自动提交)。
    mysql> select @@autocommit;
    +--------------+
    | @@autocommit |
    +--------------+
    |            1 |
    +--------------+
    1 row in set (0.01 sec)
    
    默认事务开启的作用是什么?
        当我们去执行一个sql语句的时候,效果会立即体现出来,且不能回滚。
        
2、事务回滚:撤销sql语句执行效果------rollback;
        例子:
            插入数据
            insert into user values(1,'a',1000);
            
            mysql> rollback;
            Query OK, 0 rows affected (0.00 sec)
            
            查询是否有插入成功,发现,插入成功,撤销没有效果。
            
            
            解决方法:设置mysql自动提交为false
            
            set autocommit=0;
            
            mysql> set autocommit=0;set
            Query OK, 0 rows affected (0.04 sec)

            mysql> select @@autocommit;      上面的操作,设置了mysql的自动提交为关闭
            +--------------+
            | @@autocommit |
            +--------------+
            |            0 |
            +--------------+
            1 row in set (0.00 sec)
            
            
            mysql> select * from user;
            +----+----------+
            | id | name     |
            +----+----------+
            |  1 | zhangsan |
            +----+----------+
            1 row in set (0.04 sec)

            mysql> insert into user values(2,'lisi');
            Query OK, 1 row affected (0.11 sec)

            mysql> rollback;            撤销操作
            Query OK, 0 rows affected (0.00 sec)

            mysql> select * from user;    当autocommit=0时,撤销成功。
            +----+----------+
            | id | name     |
            +----+----------+
            |  1 | zhangsan |
            +----+----------+
            1 row in set (0.00 sec)
            
            
            再一次插入数据:
            mysql> insert into user values(2,'lisi');
            Query OK, 1 row affected (0.11 sec)
            
            手动提交:
            mysql> commit;
            Query OK, 0 rows affected (0.04 sec)
            
            撤销操作:
            mysql> rollback;
            Query OK, 0 rows affected (0.00 sec)
            
            查询数据,发现无法撤销,因为commint手动提交了
            mysql> select * from user;
            +----+----------+
            | id | name     |
            +----+----------+
            |  1 | zhangsan |
            |  2 | lisi     |
            +----+----------+
            2 rows in set (0.00 sec)


    自动提交? @@autocommit;
    手动提交? commit;
    事务回滚? rollback;
    
    如果说这个时候转账:
        金额没有改变,可以使用rollback来返回
        
    当@@autocommit为1时,可以使用begin;或者start transaction;都可以手动开启一个事务,在修改语句之前使用
    
    
事务的四大特征:
    A:原子性:事务是最小的单位,不可以在分割
    C:一致性:事务要求,同一事务中的sql语句,必须保证同时成功或者同时失败
    I:隔离性:事务1 和 事务2 之间是具有隔离性的。
    D:持久性:事务一旦结束(commit,rollback),就不可以返回 
    

事务开启:
    1、修改默认提交, set autocommit=0;
    2、begin;
    3、start transaction;
    
事务手动提交:
    commit;
    
事务手动回滚:
    rollback;
    
事务的隔离性:
    1、read uncommitted;    读未提交的
    2、read committed;        读已经提交的
    3、repeatable read;    可以重复读的
    4、serializable;        串行化
    
    
    1、read uncommitted
        如果有事务a,事务b,a 事务对数据进行操作,在操作的过程中,事务没有被提交,但是b 可以看见 a操作的结果
        
        
        例子:
            bank数据库,user表
            insert into user values(3,'xiaoming',1000)
            insert into user values(4,'taobao',1000)
            
        1、如何查看数据库的隔离级别:
            mysql 5.6:
            SELECT @@tx_isolation
            
            系统级别:----mysql默认级别
            mysql> SELECT @@global.tx_isolation;
            +-----------------------+
            | @@global.tx_isolation |
            +-----------------------+
            | REPEATABLE-READ       |
            +-----------------------+
            1 row in set (0.00 sec)


            会话级别:
            mysql> SELECT @@tx_isolation;
            +-----------------+
            | @@tx_isolation  |
            +-----------------+
            | REPEATABLE-READ |
            +-----------------+
            1 row in set (0.00 sec)
            
            
        2、如何修改隔离级别:
        
            将隔离级别修改为:uncommitted
            mysql> set global transaction  isolation level read uncommitted;
            Query OK, 0 rows affected (0.00 sec)

            mysql> SELECT @@global.tx_isolation;
            +-----------------------+
            | @@global.tx_isolation |
            +-----------------------+
            | READ-UNCOMMITTED      |
            +-----------------------+
            1 row in set (0.00 sec)

            
            例子:小明买双鞋子付出800,淘宝店得到800
            start transaction;
            update user set money=money-800 where name='xiaoming';
            update user set money=money+800 where name='taobao';
            
            然后淘宝去进货付出1800,(两个初始为1000),发现钱不够,原来小明使用了rollback撤销了,所有数据变成了初始的每人1000。
            
            问题来了,开启 read uncommitted 后:
            如果两个不同的地方,都在进行操作,如果事务a read 开启之后,他的数据可以被其他事务读取到,这样就会出现(脏读),脏读:一个事务读到了另外一个事务没有提交的数据
            
    2、read committed
        
        将隔离级别修改为:committed
            mysql> set global transaction  isolation level read committed;
            Query OK, 0 rows affected (0.00 sec)

            mysql> SELECT @@global.tx_isolation;
            +-----------------------+
            | @@global.tx_isolation |
            +-----------------------+
            | READ-COMMITTED        |
            +-----------------------+
            1 row in set (0.00 sec)
            
            
        员工A在使用查询命令:
            mysql> select * from bank;
            +------+------+-------+
            | id   | name | money |
            +------+------+-------+
            |    1 | mo   | 1000  |
            |    2 | li   | 1000  |
            +------+------+-------+
            2 rows in set (0.00 sec)
            
        
        员工B在提交数据:
            start transaction;
            insert into bank values(3,'hu',8000);
            commit;
            
            mysql> select * from bank;
            +------+------+-------+
            | id   | name | money |
            +------+------+-------+
            |    1 | mo   | 1000  |
            |    2 | li   | 1000  |
            |    3 | hu   | 8000  |
            +------+------+-------+
            3 rows in set (0.00 sec)
            
        员工A 进行求平均数操作:
            mysql> select avg(money) from bank;
            +--------------------+
            | avg(money)         |
            +--------------------+
            | 3333.3333333333335 |
            +--------------------+
            1 row in set (0.07 sec)
            
            
            问题来了,当时A员工查询出来的时候没有3号的信息,毕竟实际数据太多,不可能一一对比,虽然我只能读到另一个事务提交的数据,但还是会出现问题,就是:读取同一个表的数据,发现前后不一致。
            
            此现象叫:不可重复现象:read committed


    3、repeatable read
    
        设置为 可以重复读的 :
        mysql> set global transaction  isolation level repeatable read;
        Query OK, 0 rows affected (0.02 sec)

        mysql> SELECT @@global.tx_isolation;
        +-----------------------+
        | @@global.tx_isolation |
        +-----------------------+
        | REPEATABLE-READ       |
        +-----------------------+
        1 row in set (0.00 sec)

        
        例子:
            现有两人:
                
                员工A 手动开启一个事务:
                    start transaction;
                    
                
                员工B 在另外一个窗口进入数据库,也手动开启一个事务:、
                    start transaction;
                    
                员工A 插入一条数据:
                    insert into bank values(6,'b','100');
                    commit
                    
                员工B 也插入相同的数据:
                    insert into bank values(6,'b','100');
                    
                    出错!!
                    
            这种现象,我们叫他“幻读”
            事务a 和 事务b 同时操作一张表,事务a 提交的数据,也不能被事务b 读到,这就造成幻读。
            
    
    4、serializable;        串行化
        
        mysql> set global transaction  isolation level serializable;
        Query OK, 0 rows affected (0.00 sec)


        mysql> SELECT @@global.tx_isolation;
        +-----------------------+
        | @@global.tx_isolation |
        +-----------------------+
        | SERIALIZABLE          |
        +-----------------------+
        1 row in set (0.00 sec)
        
        例子:
            现有两人:
                
                员工A 手动开启一个事务:
                    start transaction;
                    
                
                员工B 在另外一个窗口进入数据库,也手动开启一个事务:、
                    start transaction;
                    
                员工A 插入一条数据:
                    insert into bank values(6,'b','100');
                    commit 
                    
                员工B 也插入相同的数据:
                    select * from bank;  ----------发现,已经被同步过来了,不需要再次插入
                    
                    
                员工A 再次插入一条数据:
                    start transaction;
                    insert into bank values(7,'d','100');  ---------发现卡住了,原因是:员工B 开启了start transaction,需要其commit后才能继续操作
                    
                    
        结论:当bank 表被另一个事务操作的时候,其他事务里面的写操作,是不可以进行的。进入排队状态(串行化),直到员工B commit后,员工B 才能进行操作。前提,在没有等待超时的情况下。
        
        所以串行化的问题是:性能差!!
        性能级别:read uncommitted;读未提交 > read committed;读已经提交的 > repeatable read;可以重复读的 > serializable;串行化
        
        mysql 默认级别为:repeatable read;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值