什么是事务?
事务是逻辑上的一组操作,要么都执行,要么都不执行。
事务的ACDI特性:
A(Atomicity):原子性,事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
C(Consistency):一致性,执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;
D(Durability):持久性,并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
I(Isolation):隔离性,一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
事务并发带来的问题
当多个事务并发运行,不进行隔离会带来的问题:
脏读是指当一个事务正在修改数据,还没有提交到数据库,但另一个事务也访问了这个数据,然后使用了这个数据,因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。
幻读是指由于事务的插入或删除操作,在一个事务内看到数据的个数不一样的情况,在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
不可重复度是指由于事务的修改,另一个事务在访问时,读到两个不一样的数据。指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。
丢失修改:指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。
MySQL的默认存储引擎InnoDB支持事务,MyISAM不支持事务。所谓事务,在MySQL中就是一组“在一条船上的”DML语句,它们之间有逻辑关联性,他们“同生共死”.
事务的操作
事务中还有一个非常重要的概念叫做保存点:处于事务开始和结束之间,设置一个叫做保存点的东西,他能够保留事务进展的中间过程,这样做的好处在于,当事务的DML语句一旦失败,不会使得全部DML语句失败从而只能回滚回到事务开始,而是回滚到保存点保存的语句位置,因此保存点以前的事务都能得以存留,不会全部失败,提高了工作效率,便于回滚。
但是事务一旦提交,保存点失效,回滚也不能生效。
开始一个事务
start transaction;
创建一个保存点
savepoint 保存点名;
回到保存点(根据具体情况)
rollback to 保存点名;
提交事务
commit;
事务的隔离级别
因此需要对数据库进行隔离操作:
设置事务隔离级别:
set session transaction isolation level read uncommitted?读未提交:会出现脏读,幻读,不可重复读,不加锁读)
set session transacion isolation level read committed;(读已提交:会出现幻读、不可重复读、不加锁读)
set session transaction isolation levael repeatable read;(可重复读:会出现不加锁读)
set session transaction isolation levael serializable;(可串行化:加锁读)
可串行化:当客户端A执行可串行化隔离时,执行了select 语句,DBMS就会对库加锁,
此时有客户端B要执行update操作时,只要锁没释放,就会把客户端B放入等待队列,直到锁释放。
查看当前隔离级别:
select @@tx_isolation;
视图特性
视图是一个虚拟的表,其内容由查询定义,但是视图的变化会影响到基表,基表变化也会影响到视图。,视图可以提高安全性,但也必须具有足够的权限,因此还与后面提到的用户管理知识息息相关。
创建视图
create view 视图名 as select语句
若select语句中有order by 语句在视图中也使用order by 语句,会以select中的order by 语句为准,后者的order by 语句不生效。
视图不能添加索引,也不能有关联的出发器
用户管理
root 用户拥有所有权限,如果只使用root用户,会带来安全隐患。因此需要创建新的用户,并赋予一旦定的权限,以此规避安全隐患。
创建用户:
create user '用户名'@‘登陆主机’/ip identified by ‘密码’;
删除用户:
drop user '用户名'@‘主机名’;
修改用户密码
1.自己改自己密码
set passworld = passworld('新密码');
2.root 用户修改指定用户密码
set passworld for '用户名'@‘主机名’=passworld('新的密码');
数据库的权限列表:
给用户授权:
grant 权限列表 on 库.对象名 to '用户名'@'登陆位置' [identified by '密码']
如果赋权限未生效:
flush privileges;
回收权限:
revoke 权限列表 on 库.对象名 from ‘用户名’@‘登陆位置’;