事务:一组原子性的SQL查询,或者说一个独立工做单元。
事务日志:
在Oracle当中,被分解为redo log、undo log,及所谓重作日志和撤销日志
ACID测试:
A:atomicity,原子性;整个事务中的全部操做要么所有成功执行,要么所有失败后回滚;
C:conststency,一致性;数据库老是从一个一致性状态转换为另外一个一致性状态;
I:Isolation,隔离性;一个事务所作出的操做在提交以前,是不能为其它所见;
D:durability;持久性;一但事务提交,其所作的修改会永久保存于数据库中;
隔离有多种隔离级别;
隔离级别越高,数据的安全性越高,不过它的并发能力就越低,隔离级别越低、并发性就越好,可是数据安全性差
事务:
启动事务:start transaction
结束事务:
一、comit;提交
二、rollback;回滚
注意;只有事务型存储引擎方能支持此类操做;
建议:显示请求和提交事务,而不要使用“自动提交”功能;
autocommit={1|0}
示例:
关闭autocommit
MariaDB [hellodb]> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> show variables like '%auto%';
+--------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
| autocommit | OFF |
+--------------------------------------+-------+
开始事务
MariaDB [hellodb]> start transaction;
删除学生表里面的stuid是18和23的学员
MariaDB [hellodb]> delete from students where stuid in (18,23);
执行rollback 回滚
MariaDB [hellodb]> rollback;
事务支持savepoint
SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier
savepoint示例:
# 开始事务
MariaDB [hellodb]> start transaction;
Query OK, 0 rows affected (0.00 sec)
# 先查看下最初的students表里面的全部内容
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
# 执行delete语句删除学员编号为18的学员信息
MariaDB [hellodb]> delete from students where stuid=18;
Query OK, 1 row affected (0.00 sec)
# 建立一个事务还原点为sp1
MariaDB [hellodb]> savepoint sp1;
Query OK, 0 rows affected (0.00 sec)
# 插入一条信息
MariaDB [hellodb]> insert into students (name,age,gender) values('Jinjiao King',100,'M');
Query OK, 1 row affected (0.00 sec)
# 建立一个事务还原点为sp2
MariaDB [hellodb]> savepoint sp2;
Query OK, 0 rows affected (0.00 sec)
# 使用update语句更新13号学员的年龄
MariaDB [hellodb]> update students set age=43 where stuid=13;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
# 上述操做作完以后查看下表是否发生变化
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 43 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
| 26 | Jinjiao King | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
# 对students操做完以后,假如说其中有数据有问题,而后回到以前建立的sp2上
MariaDB [hellodb]> rollback to sp2;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
| 26 | Jinjiao King | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
# 回滚到以前建立sp1的状态上
MariaDB [hellodb]> rollback to sp1;
Query OK, 0 rows affected (0.00 sec)
# 所有回滚到最初状态
MariaDB [hellodb]> rollback;
Query OK, 0 rows affected (0.00 sec)
事务隔离级别
事务隔离级别:
事务自己是须要隔离的,但隔离作的过于严格,任何一个事务都会阻塞其它访问同一个资源的事务,为了不事务过多的影响其所谓的并发性,咱们对事务关系型标准当中对事务的隔离等级作定义,每一种关系型数据库,均可以设定本身到底支持哪一种级别,大多数数据库默认状况下都支持到第二种,但mysql支持第三级别
事务的四种隔离级别:(mysql默认是REPEATABLE READ 可重复读)
READ UNCOMMITED (读未提交)
脏读、不可重复读、幻读
READ COMMITTED (读提交)
不可重复读、幻读
REPEATABLE READ (可重读)
幻读
SERIALIZABILE (可串行化)
加锁读
可能存在问题:
脏读: 读别人未提交的数据
不可重复读: 读别人提交的数据也能够,可是别人提交之后产生一个问题查看的结果是以前看到的数据,看不到后面提交的新数据,不可重复读,两次读到的数据是不同的
幻读: 即读取过程当中,即便有其它提交的事务修改数据,仍只能读取到未修改前的旧数据。
加锁读:
tx_isolation:服务器变量,默认为REPEATABLE-READ;可在session级别进行修改
MVCC:多版本并发控制
死锁:
两个或多个事务在同一资源相互占用,并请求锁定对方占用的资源的状态;
数据库为了解决这样的问题,设计了各类死锁检测、和死锁超时时长
事务日志:
事务日志的写入类型为“追加”、所以其操做为“顺序IO”,此日志一般也被称为“预写式日志(write ahead logging)”;
innodb_log_file_size
innodb_log_files_in_group
innodb_log_group_home_dir
事务的隔离级别示例:
脏读实验:
为了实验效果多开一个会话窗口,而且两边都把autocommit自动提交事务给关闭掉
MariaDB [hellodb]> set autocommit=0;
MariaDB [hellodb]> show variables like '%auto%';
+------------------------------+-------+
| Variable_name | Value |
+------------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
| autocommit | OFF |
+------------------------------+-------+
一、把两个会话改成READ-UNCOMMITTED模式;
MariaDB [hellodb]> show global variables like '%isola%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
MariaDB [hellodb]> set tx_isolation='READ-UNCOMMITTED';
Query OK, 0 rows affected (0.00 sec)
在两个会话上都启用事务
MariaDB [hellodb]> start transaction;
Query OK, 0 rows affected (0.00 sec)
在第一个会话中修改students表里面的13号学员的年龄为40
MariaDB [hellodb]> update students set age=40 where stuid=13;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MariaDB [hellodb]> select * from students where stuid=13;
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 13 | Tian Boguang | 40 | M | 2 | NULL |
+-------+--------------+-----+--------+---------+-----------+
1 row in set (0.00 sec)
而后在第二个会话里面查看是否是能看到13号学员的修改后的数据库此时第一个窗口并未提交事务
MariaDB [hellodb]> select * from students where stuid=13;
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 13 | Tian Boguang | 40 | M | 2 | NULL |
+-------+--------------+-----+--------+---------+-----------+
1 row in set (0.00 sec)
----------------------------------------------------------------------------------------
REPEATABLE-READ模式:
设置为REPEATABLE-READ
MariaDB [hellodb]> set tx_isolation='REPEATABLE-READ';
Query OK, 0 rows affected (0.00 sec)
删除stuid为3的学员
MariaDB [hellodb]> delete from students where stuid=3;
Query OK, 1 row affected (0.00 sec)
在第一会话提交事务
MariaDB [hellodb]> commit;
Query OK, 0 rows affected (0.00 sec)
在第一会话查询stuid为3的已经查不到了
MariaDB [hellodb]> select * from students where stuid=3;
Empty set (0.00 sec)
在第二个会话中查询仍是能够查询到,这就产生了幻读,这种模式解决了不可重复读,不过仍是避免不了幻读的问题
MariaDB [hellodb]> select * from students where stuid = 3;
+-------+-----------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-----------+-----+--------+---------+-----------+
| 3 | Xie Yanke | 53 | M | 2 | 16 |
+-------+-----------+-----+--------+---------+-----------+
1 row in set (0.00 sec)
只有在第二会话中执行提交事务以后再次查询就没有出现了
MariaDB [hellodb]> commit;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> select * from students where stuid=3;
Empty set (0.00 sec)
----------------------------------------------------------------------------------
SERIALIZABLE 加锁读示例:
一、设置模式为SERIALIZABLE
MariaDB [hellodb]> set tx_isolation='SERIALIZABLE';
Query OK, 0 rows affected (0.00 sec)
二、修改stuid为14的年龄
MariaDB [hellodb]> update students set age=21 where stuid=14;
三、在本窗口查询修改结果
MariaDB [hellodb]> select * from students where stuid=14;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 14 | Lu Wushuang | 21 | F | 3 | NULL |
+-------+-------------+-----+--------+---------+-----------+
四、在第二个会话窗口查询,只要执行查询以后就会被阻塞,而后过了必定时长系统会提示超时
MariaDB [hellodb]> select * from students;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
五、第一窗口执行提交事务
MariaDB [hellodb]> commit;
Query OK, 0 rows affected (0.02 sec)
六、再在第二窗口查询,就能够查询
MariaDB [hellodb]> select * from students where stuid=14;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 14 | Lu Wushuang | 21 | F | 3 | NULL |
+-------+-------------+-----+--------+---------+-----------+
1 row in set (0.00 sec)