保持数据库的纯粹性:完整性约束实际用不到,存储过程也不用。更新丢失也是程序员控制。
事务的四个条件ACID:
Autmic: 原子性,事务中的全部操作在数据库中是不可分割的,要么不做,要么全做!
Consistency: 一致性,在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。转账。
用户事务角度:(除了当前事务)其他任何事务看到的数据都是一样的。
事务A:begin;update...;select的结果是更新的,不是更新前。但别的事务看到是更新前的。
Isolation:
一个事务的执行不受其他并发执行的事务的影响。
T2查看数据时,不能查看到中间状态的数据,要么是T1修改它之前的状态,要么是T1修改它之后的状态。
Durability: 事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。
ACID实现方式,主要有两种:Write ahead logging,日志方式。第二种是Shadow paging。
数据不一致性:
1、丢失数据更新:T1,T2同时更新一条记录R,T1更新Col2时会把所有的列set(不然需要对比new,old两个对象,代价更高)
T2更新Col3时也会set所有列,覆盖了T1的操作。应该在T1事务结束后再开始T2。
2、脏读:事务2读到了事务1修改后的数据(这个数据可能被回滚,也可能被提交) 。
3、不可重复读:一个事务范围内两个相同的查询却返回了不同数据。
4、幻读:T1对表中所有行修改,T2插入/删除一行,T1发现还有未修改的数据。解决方法:增加范围锁RangeS。
事务隔离级别:
Read Uncommited(0) : 可以读脏数据
Read Commited(1)(Oracle默认):避免脏读,但可以出现不可重复读和幻读
Repeatable Read(2)(MysqL默认):避免脏读,不可重复读,允许幻像读
Serialiazble(3):序列化读
乐观锁--悲观锁
mysql,支持for update,不支持 for update nowait
show engines; //查询支持的引擎,默认为InnoDB
show variables like '%storage_engine%'; //查询当前引擎
show variables //查询mysql系统变量
show create table user; //查询mysql建表语句(处理过,真正执行的,包含一些默认值,比如ENGINE=InnoDB)
悲观锁使用for update;实现,用于冲突多时
mysql,支持for update,不支持 for update nowait
打开两个cli: c1,c2
c1,
begin; //如果不打开事务,都不阻塞
select * from user1 for update;
c2,
select * from user1 for update;阻塞至c1-commit
select * from user1;不阻塞
insert into user1(name) values('ok9');阻塞至c1-commit
乐观锁使用version实现(每次提交自增一次)适用于冲突少的情况。
嵌套子查询? //是原子操作吗?
check约束?
如何实现?
行锁,表锁
select for update必须在一个事务中(begin;...;commit;),才能起作用
主键明确时,row lock
select * from user1 where (id=11 or id=12) for update;
阻塞
update user1 set name='kkk' where id=11;
select * from user1 where (id=11 or id=12) for update;
for update/在事务中,两个缺一,select都不会阻塞
主键不明确是,table lock
数据库约束:
数据完整性:指数据的正确性和一致性,主要有两种方式:
1、定义表时定义完整性约束,约束分为两类:行级和表级。行级约束放在列后,表级约束放在表后,多个列共用的约束放在表后。
2、也可以通过规则,索引,触发器等。
3、完整性约束是一种规则,存在数据字典中,在执行SQL时。用户可以指明约束是启用的还是禁用的,启用约束会增强数据的完整性。
数据库完整性约束
比如字段A=字段B+字段C,否则insert失败。
constraint约束类型,五种:
UNIQUE和Primary Key, Foreign Key, CHECK, NOT NULL, DEFAULT