MYSQL中,FLOAT,DOUBLE,DECIMAL 都可以存储小数,但是FLOAT/DOUBLE 存储的是近似值,对于money等对精度要求高的场合不适用。
DECIMAL 类型以字符串形式存储,支持精确的小数运算。
MySQL的表级锁有两种模式:
表共享读锁、表独占写锁
不支持事务、行锁定和外键,因此当INSERT(插入)或UPDATE(更新)数据时即写操作需要锁定整个表,效率便会低一些。
如果表的读操作远远多于写操作且不需要数据库事务的支持,那么MyIASM也是很好的选择。
MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁。
只有在你增删改查时匹配的条件字段带有索引时,innodb才会使用行级锁,在你增删改查时匹配的条件字段不带有索引时,innodb使用的将是表级锁。
共享锁(读锁S):一个事务获取了一个数据行的共享锁,其他事务能获得该行对应的共享锁,但不能获得排他锁。一个事务在读取一个数据行的时候,其他事务也可以读,但不能对该数据行进行增删改。
排他锁(写锁X):一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁(排他锁或者共享锁),即一个事务在读取一个数据行的时候,其他事务不能对该数据行进行增删改查。
记录锁 | 记录锁就是为某行记录加锁,它封锁该行的索引记录 |
间隙锁 | 间隙锁基于非唯一索引 ,它锁定一段范围内的索引记录 。、使用间隙锁锁住的是一个区间,而不仅仅是这个区间中的每一条数据。 |
临键锁 | Next-Key 可以理解为一种特殊的间隙锁。通过临建锁可以解决幻读 的问题。 每个数据行上的非唯一索引列 上都会存在一把临键锁,当某个事务持有该数据行的临键锁时,会锁住一段左开右闭区间的数据。 |
age
列潜在的临键锁
有:
(-∞, 10],
(10, 24],
(24, 32],
(32, 45],
(45, +∞],
另外,为了允许行锁和表锁共存,实现多粒度锁机制,引入意向锁。
InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。
意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
意向锁产生的主要目的是为了处理行锁和表锁之间的冲突,用于表明某个事务正在某一行上持有了锁,或者准备去持有锁。
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。
ReenTrantLock的实现是一种自旋锁,通过循环调用CAS操作来实现加锁
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制或CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量。
CAS操作需要我们提供一个期望值,当期望值与当前线程的变量值相同时,说明还没线程修改该值,当前线程可以进行修改,也就是执行CAS操作,但如果期望值与当前线程不符,则说明该值已被其他线程修改,此时不执行更新操作,但可以选择重新读取该变量再尝试再次修改该变量,也可以放弃操作。
ABA问题:
ABA问题可以使用带参数版本解决,在读取和替换时判断版本。
上述并发环境下,并发1在修改数据时,虽然还是A,但已经不是初始条件的A了,中间发生了A变B,B又变A的变化,此A已经非彼A,数据却成功修改,可能导致错误,这就是CAS引发的所谓的ABA问题。
脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。可通过MVCC避免幻读。
事务是数据库一组读写操作的集合。
所有事务都可以看到没有提交事务的数据。
事务成功提交后才可以被查询到。
mysql默认级别。
强制的进行排序,在每个读读数据行上添加共享锁。会导致大量超时现象和锁竞争。
一般来说,事务的隔离级别越高,越能保证数据库的完整性和一致性,但相对来说,隔离级别越高,对并发性能的影响也越大。因此,通常将数据库的隔离级别设置为 Read Committed,即读已提交数据,它既能防止脏读,又能有较好的并发性能。虽然这种隔离级别会导致不可重复读、幻读和第二类丢失更新这些并发问题,但可通过在应用程序中采用悲观锁和乐观锁加以控制。
调用连接器连接数据库。
连接建立后,执行查询语句的时候,会先查询缓存,Mysql会先校验这个sql是否执行过,以Key-Value的形式缓存在内存。如果缓存key被命中,就会直接返回给客户端。
mysql 没有命中缓存,那么就会进入分析器,进行词法分析,语法分析
优化器的作用就是它认为的最优的执行方案去执行(虽然有时候也不是最优),比如多个索引的时候该如何选择索引,多表查询的时候如何选择关联顺序等。
当选择了执行方案后,mysql就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果。