事务
概述:
数据库的事务(Transaction)是一种机制、一个操作序列,包含了一组数据库操作命令。事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行,因此事务是一个不可分割的工作逻辑单元。
事务特性:
原子性
事务是一个完整的操作。事务的各元素是不可分的(原子的)。事务中的所有元素必须作为一个整体提交或回滚。如果事务中的任何元素失败,则整个事务将失败。事务在执行过程中如果发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。一致性
在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。当事务成功完成时,数据必须再次回到已知的一致状态。通过事务对数据所做的修改不能损坏数据,或者说事务不能使数据存储处于不稳定的状态。隔离性
数据库允许多个并发事务同时对其数据进行读写和修改的能力,事务必须为独立的,不应该改以任何方式依赖于或影响其他事务,修改数据的事务可以在另一个使用相同数据的事务开始之前访问这些数据,或者在另一个使用相同数据的事务结束之后访问这些数据。隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。持久性
事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
隔离级别
读未提交(Read uncommitted)
安全性最差,可能发生并发数据问题,性能最好读提交(read committed)
Oracle默认的隔离级别可重复读(repeatable read)
MySQL默认的隔离级别,安全性较好,性能一般串行化(Serializable)
表级锁,读写都加锁,效率低下,安全性高,不能并发
MySQL事务处理
默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务,若要在一个事务中包含多条SQL语句,需要手动开启事务。
- 开启事务:start transaction
- 结束事务:commit(提交事务)或rollback(回滚事务)
执行SQL语句前需要执行start transaction开启事务,再去执行多条SQL语句,最后结束事务,commit提交事务或者rollback回滚事务,commit表示事务中的多条SQL语句做出的数据改变将会持久化到数据库中,rollback表示回滚,回滚至事务的起点。
事务处理
- 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务
- 事务处理可以用来维护数据的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行
- 事务用来管理 insert、update、delete 语句,因为这些操作才会“破坏”数据,查询select语句是不会的
- MySQL默认数据库的事务是开启的,执行SQL后自动提交。
- MySQL的事务也可以改成手动提交,那就有两个步骤:先开启,写完SQL后,再手动提交。
提交
多条语句时,批量执行,事务提交
有了事务,多步操作就形成了原子性操作,高并发下也不会引起数据错乱
mysql的事务默认就是开启的 — 多条语句一起操作时,要么一起成功要么一起失败
BEGIN; 关闭事务的自动提交
回滚
多条语句,批量执行,insert插入重复的主键导致失败时,事务回滚
mysql> start transaction; #开启事务
Query OK, 0 rows affected (0.00 sec)
mysql> insert into dept values(18,'java','shanghai');
Query OK, 1 row affected (0.00 sec)
mysql> insert into dept values(19,'java2','shanghai2');
Query OK, 1 row affected (0.00 sec)
mysql> commit; #提交事务
Query OK, 0 rows affected (0.03 sec)
约束
- 默认约束
CREATE TABLE x(
id INT PRIMARY KEY AUTO_INCREMENT,
sex VARCHAR(10) DEFAULT '男' #设置默认值
);
- 外键约束
一个表中的外键FOREIGN KEY指向另一个表的主键PRIMARY KEY
使用指定SQL语句描述两张表的关系。
子表添加记录时id必须取自主表
删除主表记录时,子表id不可有与主表id相关联的记录,否则报错
拥有外键的表为子表 ```sql CREATE TABLE tb_user( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(10), sex VARCHAR(10) );
CREATE TABLE tb_user_address( user_id INT PRIMARY KEY AUTO_INCREMENT, address VARCHAR(20), FOREIGN KEY(user_id) REFERENCES tb_user(id) #s );
SELECT FROM tb_user SELECT FROM tb_user_address INSERT INTO tb_user VALUES(NULL,’马钊’,’男’) INSERT INTO tb_user VALUES(NULL,’泡泡’,’女’) INSERT INTO tb_user_address VALUES(NULL,’济南’) DELETE FROM tb_user WHERE id = 1;#报错,因为id为1的记录在子表中有其对应的user_id,只有当对应的user_id被删除后才可删除 DELETE FROM tb_user WHERE id = 2;#成功,因为id为2的记录在子表中没有与其对应的user_id
3.
检查约束
```sql
CREATE TABLE a(
id INT PRIMARY KEY AUTO_INCREMENT,
age INT,
CHECK(0 < age AND age < 200)#设置检查
);