Redis

Redis REmote DIctionary Server(Redis) 是一个由SalvatoreSanfilippo写的key-value存储系统。 Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash (哈希类型) 。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了 master-slave (主从)同步。 Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。 Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。 redis的官网地址,非常好记,是redis.io。 (特意查了一下,域名后缀io属于国家域名,是british Indian Ocean territory,即英属印度洋领地) 目前,Vmware在资助着redis项目的开发和维护。redis[2] 的作者,叫Salvatore Sanfilippo,来自意大利的西西里岛,现在居住在卡塔尼亚。目前供职于Pivotal公司。他使用的网名是antirez。 Redis 4.0 之后的版本,情况就有了一些变动,新版的 Redis 服务在执行一些命令时就会使用『主处理线程』之外的其他线程,例如 UNLINK、FLUSHALL ASYNC, FLUSHDB ASYNC 等非阻塞的删除操作。 Redis 在较新的版本中引入了多线程,不过是在部分命令上引入的,其中包括非阻塞的删除操作,在整体的架构设计上,主处理程序还是单线程模型的 线程模型 使用单线程模型能带来更好的可维护性,方便开发和调试; 使用单线程模型也能并发的处理客户端的请求; Redis 服务中运行的绝大多数操作的性能瓶颈都不是 CPU 6.0 Redis 的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程。之所以这么设计是不想因为多线程而变得复杂 I/O 多路复用的主要作用是让我们可以使用一个线程来监控多个连接是否可读或者可写,但是从网络另一头发的数据包需要先解序列化成 Redis 内部其他模块可以理解的命令,这个过程就是 Redis 6.0 引入多线程来并发处理的。 I/O 多路复用模块收到数据包之后将其丢给后面多个 I/O 线程进行解析,I/O 线程处理结束后,主线程会负责串行的执行这些命令,由于向客户端发回数据包的过程也是比较耗时的,所以执行之后的结果也会交给多个 I/O 线程发送回客户端。 AOF AOF 是 Redis 的一种持久化机制,它会在每次收到来自客户端的写请求时,将其记录到日志中,每次 Redis 服务器启动时都会重放 AOF 日志构建原始的数据集,保证数据的持久性。 Keyspace Notifications, 键空间通知 在Redis2.8.0版本的时候,推出 Keyspace Notifications future。 Keyspace Notifications 此特性允许客户端可以以 订阅/发布 (Sub/Pub) 模式,接收那些对数据库中的键和值有影响的操作事件。这些操作事件具体来说,就是 hash , del, expire , set , lpop 等。 那么你可能会问,redis keyspace 到底有啥用处? 简单说,对于我个人主要关注keyspace几个扩展场景: ...

2015-07-13 · 2 min · 357 words · -

丢失更新, 脏读、幻读和不可重复读

丢失更新, 脏读、幻读和不可重复读 http://uule.iteye.com/blog/1109647 脏读、幻读和不可重复读 + 事务隔离级别 博客分类: 数据库 需学习 ITeyeBlog.net 丢失更新: 两个事务同时更新一行数据,最后一个事务的更新会覆盖掉第一个事务的更新,从而导致第一个事务更新的数据丢失,这是由于没有加锁造成的; 脏读 : 脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。 e.g. 1.Mary的原工资为1000, 财务人员将Mary的工资改为了8000(但未提交事务) 2.Mary读取自己的工资 ,发现自己的工资变为了8000,欢天喜地! 3.而财务发现操作有误,回滚了事务,Mary的工资又变为了1000 像这样,Mary记取的工资数8000是一个脏数据。 不可重复读 : 是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。 e.g. 1.在事务1中,Mary 读取了自己的工资为1000,操作并没有完成 2.在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务. 3.在事务1中,Mary 再次读取自己的工资时,工资变为了2000 解决办法: 如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题。 幻读 : 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。 e.g. 目前工资为1000的员工有10人。 1.事务1,读取所有工资为1000的员工。 2.这时事务2向employee表插入了一条员工记录,工资也为1000 3.事务1再次读取所有工资为1000的员工 共读取到了11条记录, 解决办法: 如果在操作事务完成数据处理之前,任何其他事务都不可以添加新数据,则可避免该问题 不可重复读的重点是修改 : 同样的条件, 你读取过的数据,再次读取出来发现值不一样了 幻读的重点在于新增或者删除 同样的条件, 第 1 次和第 2 次读出来的记录数不一样 参考: http://cupoy.iteye.com/blog/251796 http://blog.csdn.net/d8111/archive/2008/06/29/2595635.aspx http://www.iteye.com/topic/332577 在一个程序中,依据事务的隔离级别将会有三种情况发生。 ◆脏读: 一个事务会读进还没有被另一个事务提交的数据,所以你会看到一些最后被另一个事务回滚掉的数据。 ◆不可重复读: 一个事务读进一条记录,另一个事务更改了这条记录并提交完毕,这时候第一个事务再次读这条记录时,它已经改变了。 ◆ 幻影读: 一个事务用Where子句来检索一个表的数据,另一个事务插入一条新的记录,并且符合Where条件,这样,第一个事务用同一个where条件来检索数据后,就会多出一条记录。 数据库提供了四种事务隔离级别, 不同的隔离级别采用不同的锁类开来实现. 在四种隔离级别中, Serializable的级别最高, Read Uncommited级别最低. ...

2015-06-28 · 1 min · 149 words · -

聚簇索引 非聚簇索引

聚簇索引 非聚簇索引 http://blog.sina.com.cn/s/blog_6caea8bf0100z9wz.html 通常情况下,建立索引是加快查询速度的有效手段。但索引不是万能的,靠索引并不能实现对所有数据的快速存取。事实上,如果索引策略和数据检索需求严重不符的话,建立索引反而会降低查询性能。因此在实际使用当中,应该充分考虑到索引的开销,包括磁盘空间的开销及处理开销 (如资源竞争和加锁) 。例如,如果数据频繁的更新或删加,就不宜建立索引。 本文简要讨论一下聚簇索引的特点及其与非聚簇索引的区别。 建立索引: 在SQL语言中,建立聚簇索引使用CREATE INDEX语句,格式为: CREATE CLUSTER INDEX index_name ON table_name(column_name1,column_name2,…); 存储特点: 聚集索引。表数据按照索引的顺序来存储的,也就是说索引项的顺序与表中记录的物理顺序一致。对于聚集索引,叶子结点即存储了真实的数据行,不再有另外单独的数据页。 在一张表上最多只能创建一个聚集索引,因为真实数据的物理顺序只能有一种。 非聚集索引。表数据存储顺序与索引顺序无关。对于非聚集索引,叶结点包含索引字段值及指向数据页数据行的逻辑指针,其行数量与数据表行数据量一致。 总结一下: 聚集索引是一种稀疏索引,数据页上一级的索引页存储的是页指针,而不是行指针。而对于非聚集索引,则是密集索引,在数据页的上一级索引页它为每一个数据行存储一条索引记录。 更新表数据 1、向表中插入新数据行 如果一张表没有聚集索引,那么它被称为"堆集" (Heap) 。这样的表中的数据行没有特定的顺序,所有的新行将被添加到表的末尾位置。而建立了聚簇索引的数据表则不同: 最简单的情况下,插入操作根据索引找到对应的数据页,然后通过挪动已有的记录为新数据腾出空间,最后插入数据。如果数据页已满,则需要拆分数据页,调整索引指针 (且如果表还有非聚集索引,还需要更新这些索引指向新的数据页) 。而类似于自增列为聚集索引的,数据库系统可能并不拆分数据页,而只是简单的新添数据页。 2、从表中删除数据行 对删除数据行来说: 删除行将导致其下方的数据行向上移动以填充删除记录造成的空白。如果删除的行是该数据页中的最后一行,那么该数据页将被回收,相应的索引页中的记录将被删除。对于数据的删除操作,可能导致索引页中仅有一条记录,这时,该记录可能会被移至邻近的索引页中,原索引页将被回收,即所谓的"索引合并"。 稀疏索引 稀疏索引只为数据文件的每个存储块设一个键-指针对,它比稠密索引节省了更多的存储空间,但查找给定值的记录需更多的时间。只有当数据文件是按照某个查找键排序时,在该查找键上建立的稀疏索引才能被使用,而稠密索引则可以应用在任何的查找键。如图3-3所示,稀疏索引只为每个存储块设一个键-指针对。键值是每个数据块中第一个记录的对应值。 例3.3同例3.2一样,我们假定数据文件已排序,且其键值为连续的10的倍数,直至某个较大的数。我们还继续假定每个存储块可存放四个键-指针对。这样,第一个索引存储块中为前四个数据存储块的第一个键值的索引项,它们分别是10、30、50和70。按照前面假定的键值模式,第二个索引存储块中为第五至第八个数据存储块的第一个键值的索引项,它们分别是90、110、130和150。图中我们还列出第三个索引存储块存放的键值,它们分别是假设的第九至第十二个数据存储块的第一个键值。 图3-3 顺序文件上的稀疏索引 在已有稀疏索引的情况下,要找出查找键值为K的记录,我们得在索引中查找到键值小于或等于K的最大键值。由于索引文件已按键排序,我们可以使用二分查找法来定位这个索引项,然后根据它的指针找到相应的数据块。现在我们必须搜索这个数据块以找到键值为K的记录。当然,数据块中必须有足够的格式化信息来标明其中的记录及记录内容,可以采用2.5节和2.7节中的任何技术。 http://book.51cto.com/art/201012/238283.htm 稠密索引和稀疏索引 稠密索引: 在密集索引中,数据库中的每个搜索键值都有一个索引记录。这样可以加快搜索速度,但需要更多空间来存储索引记录本身。索引记录包含搜索键值和指向磁盘上实际记录的指针。 稀疏索引 稀疏索引: 在稀疏索引中,不会为每个搜索关键字创建索引记录。此处的索引记录包含搜索键和指向磁盘上数据的实际指针。要搜索记录,我们首先按索引记录进行操作,然后到达数据的实际位置。如果我们要寻找的数据不是我们通过遵循索引直接到达的位置,那么系统将开始顺序搜索,直到找到所需的数据为止。 https://cloud.tencent.com/developer/article/1711134 Innodb底层存储数据 B+树索引的两种类型 聚集索引: 通过每张表的主键顺序进行存放,其叶子节点存放的是这张表的每行完整数据。也正是我们有时称呼的主键索引 (对比一下稠密索引) 非聚集索引 (辅助索引,二级索引): 其叶子节点并不包含行记录的全部数据,其叶子结点的数据包含书签和键值 (用于创建索引的字段值),书签的作用是找与索引相对应的行数据。也就是对应聚集索引的主键值。你是否有想过对应的描述的索引值 关系 看完稀疏索引和稠密索引还有聚集索引和非聚集索引的概念,我们是否能看出他们有什么关系。 聚簇索引 (主键索引)是稠密索引,因为主键索引是所有的值都不为空,每一个搜索码都会有对应的行记录。 非聚集索引是稀疏索引,非聚集索引有唯一索引,普通索引,复合索引。他们的特征就是不会为表得每个值创建搜索码,而是为单个或多个字段创建,且行记录的某些值可以为null。当我们的where条件不止单个条件的时候我们也会首先通过索引查找出来一批数据,然后进行顺序查找筛选,所以是完全复合稀疏索引的条件的。 优势 通过上面的了解,稀疏索引占用空间少,但是在查询的精确率上还是相对于稠密索引还是比较慢的,因为不需要顺序查找,还有回表。 稠密索引那就是相对来说比较快,因为他可以精确定位数据,但是占用的空间比较大。 https://cloud.tencent.com/developer/article/1711134 聚集索引,非聚集索引,主键索引,覆盖索引

2015-05-14 · 1 min · 66 words · -

数据库模型设计——关系的实现

数据库模型设计 - 关系的实现 在实体关系模型中,我们知道有三种关系: 一对一、一对多、多 http://www.cnblogs.com/studyzy/p/3309782.html 数据库模型设计——关系的实现对多。这只是概念上的关系,但是在真实的关系数据库中,我们只有外键,并没有这三种关系,那么我们就来说一说在关系数据库管理系统中,怎么实现这三种关系。 一对多 这里先讲解一对多,因为这个关系最简单。一对多和多对一是一回事,所以就不再提多对一这个词。一对多的概念是一个对象A会对应多个对象B,而从B的角度看,一个对象B只会对于一个对象A。比如说班级和学生就是一对多关系。一个班级对应多个学生,一个学生只会对于一个班级。 一对多的关系之所以说简单,是因为RDBMS的外键其实就是表示一对多关系。对于一对多关系,我们只需要在"多"的这个表中建立"一"的外键关联即可,而"一"这边的表不需要做任何修改。比如前面说到的班级学生关系。班级表不变,学生表增加班级Id作为外键。 多对多 多对多的关系在数据库设计时比一对一要常见,所以这里先说说多对多。多对多是一个对象A对应多个对象B,从B角度看,一个对象B也会对应多个对象A。比如说学生和课程的关系就是多对多关系。一个学生会学习多门课程,一门课程会有多个学生来选修。 在RDBMS中,必须使用中间表来表示多对多的关系。中间表我们可以分成两种,一种是纯粹表示关系的中间表,一种是表示中间实体的中间表。 纯粹表示关系的中间表很简单,只需要两列: AID 和 BID,AID 以外键关联到 A 表的主键,BID 以外键关联到 B 表的主键,然后这两个列组成联合主键。 这个中间表纯粹是表示多对多关系而存在, 在业务上不会有对应的实体与之对应。比如前面提到的学生和课程的关系,如果我们只需要知道哪些学生上哪些课,哪些课有哪些学生选, 不需要有更多的信息的情况下,我们就可以建立"学生课程"中间表,里面只有学生ID和课程ID两个字段。 中间实体是在纯粹的中间关系表的基础上,加上了更多的属性,从而形成了一个新的实体。比如前面提到的学生和课程的关系,如果我们需要记录学生选课的时间、学生选择这门课程后的考试成绩,那么我们就像建立一个"选课"实体,该实体具有如下属性: 选课 ID,主键 学生ID,与学生表做外键关联 课程ID,与课程表做外键关联 选课时间,DateTime类型 考试成绩,记录选修该课程后考试的最终成绩 这就是一个中间实体,已经完全脱离了普通的多对多关系中间表,而变成一个实体的形式的存在,所以按照前面博客中讲到的主键设计的原则, 我们可以单独建立一个选课ID的列作为数据库的主键,该主键本身并没有业务含义。 一对一 一对一概念上是说一个对象A最多对应一个对象B,从B角度看,也是一个对象B最多对应一个对象A。比如说班主任 (教师) 和班级的关系,一个班主任最多管理一个班级,一个班级也最多只有一个班主任。 一对一的关系在数据库设计中,是使用的最少的关系,因为一般来说,如果两个实体是一对多关系,那么我们也可以把这两个实体合并成一个实体。但是在设计中,我们仍然会遇到两个完全不同的实体,之间存在一对一关系。 一对一的RDBMS实现是在其中的一个表上建立外键指向另一个表,同时在该外键列上建立唯一约束。比如前面说到的班主任和班级关系,我们可以在班级表建立班主任字段,然后再在该字段建立唯一约束。因为每个班都会有班主任,所以班主任字段是不允许为空的。一个教师可以当某个班的班主任,也可以不当任和班的班主任,同时也不可能在班级表的班主任字段上出现两次,所以最多就当一个班的班主任,所以该设计满足需求。 那么我们可不可以反过来,在教师表中建立所管理的班级Id字段,指向班级表,并建立唯一约束呢?除了不满足"每个班必然有一个班主任"这个业务约束外,其他都没有问题。所以如果对于一对一的情况,如果那边必须要求持有另一边,则就在哪边增加外键字段;如果没有要求必须持有一个另一类实体的话,就哪边添加外键列都行。 外键与索引 外键是一种约束,与索引的概念不一样,只是大多数情况下,我们建立外键时,都会在外键列上建立对应的索引。外键的存在会在每一次数据插入、修改时进行约束检查,如果不满足外键约束,则禁止数据的插入或修改,这必然带来一个问题,就是在数据量特别大的情况下,每一次约束检查必然导致性能的下降。索引其实也有类似的问题,索引如果建多了,那么在插入删除修改数据时也要去维护对应的索引,所以索引的存在也会导致数据操作变慢。 不过外键与索引的优点不同,外键只是保证数据的一致性,并不能给系统性能带来任何好处,所以由于外键导致的插入数据变慢会随着数据量的增长而越来越严重。而索引的目的是为了检索数据更快,维护数据时导致的索引数据的变更,对性能的影响不会像外键那样随着数据量增长而变得严重 (当然大数量时的索引树维护会比小数据量的索引树维护更麻烦,但至少不是像外键那样) 。 出于性能的考虑,如果我们的系统完全由我们开发的程序使用,而不需要提供数据库给其他应用系统写入数据,而且对性能要求较高,那么我们可以考虑在生产环境中不使用外键,只需要建立能够提高性能的索引。由于整个数据库的操作都是由我们开发的程序来完成的,所以我们程序可以在开发过程中做好各方面的一致性检查,保证操作的数据是满足外键约束的,而不需要真正的存在这样一个外键约束。怎么做到这一点呢,首先,我们在建立数据库时有多个脚本,包括创建表、创建初始化数据、创建索引、创建外键等,我们在开发和测试环境中,都把这些脚本运行了,以使开发测试环境中的数据库是完整的,经过大量测试保证应用程序能够维护数据之间的约束的情况下,那么我们在生产时,并不需要运行创建外键这个脚本文件,只需要创建表、初始化数据、创建索引等即可。 【出自博客园深蓝居,转载请注明作者出处】

2015-03-23 · 1 min · 49 words · -

数据库 关系表

数据库 关系表 http://www.itokit.com/2012/0512/73913.html 关联映射: 一对多/多对一存在最普遍的映射关系,简单来讲就如球员与球队的关系;一对多: 从球队角度来说一个球队拥有多个球员 即为一对多多对一: 从球员角度来说多个球员属于一个球队 即为多对一数据表间一对多关系如下图: 关联映射: 一对一关系就如球队与球队所在地址之间的关系,一支球队仅有一个地址,而一个地址区也仅有一支球队。数据表间一对一关系的表现有两种,一种是外键关联,一种是主键关联。图示如下: 一对一外键关联: 前言: 多对多关系至少需要3个表,我们把一个表叫做主表,一个叫做关系表,另外一个叫做字典表或者副表 (字典表是纪录比较少,而且基本稳定的,例如: 版块名称;副表是内容比较多,内容变化的,例如) 。 按照数据库的增删查改操作,多对多关系的查找都可以用inner join或者 select * from 主表 where id in (select 主表id from 关系表) 1,角色任命型 特点: 关系表两外键组合无重复纪录,关系表一般不需要时间字段和主键,有一个表是字典类型的表。 界面特点: 显示主表,用checkbox或多选select设置多选关系。 例如: 任命版主 (用户表-关系表-版块名称表) ,角色权限控制等,用户是5个版块版主,只要关系表5行纪录就可以确立,关系表的两个外键具有联合主键性质。 增加关系: 如果没有组合纪录,insert之。 删除关系: 如果有组合纪录,删除之。 2,集合分组型 特点: 同角色任命型类似,关系表两外键组合无重复纪录,关系表一般不需要时间字段和主键。区别是主副表都不是字典表,可能都很大不固定。 界面特点: 显示主表,用搜索代替简单的checkbox或多选select,或者一条一条的添加。 例如: 歌曲专集 (专集表-关系表-歌曲表) 。手机分组 (分组表-关系表-手机表) 。用户圈子 (圈子表-关系表-用户表) 。文章标签 (文章表-关系表-标签表) 增加关系: 同版主任命型。 删除关系: 同版主任命型。 3,明细帐型 特点: 关系表可以有重复纪录,关系表一般有时间字段,有主键,可能还有文字型的字段用来说明每次发生关系的原因 (消费) 。 界面特点: 显示关系表,用radio或下拉设置单选关系。 例如: 现金消费明细帐或订单 (用户表-订单表-消费原因表) ,用户可能多次在同一事情上重复消费。积分变化纪录也属于这类。 ...

2015-03-23 · 1 min · 156 words · -

数据库主键设计

数据库主键设计 surrogate key (单主键), composite primary keys (联合主键) https://www.zhihu.com/question/265739203 https://stackoverflow.com/questions/2667988/why-single-primary-key-is-better-than-composite-keys 如果使用 b-tree 索引形式,有序 id 比无序 id 好,如果是 hash 索引,两个差别不大。主要原因是索引在磁盘上存储的形式, 常用的 b-tree 索引如果 id 是连续的,那么数据存储在相邻的磁盘上,如果查询和写入操作的 id 连续,那么减少随机读写硬盘的几率,提升读写效率。 作者:郭麒 链接:https://www.zhihu.com/question/43500172/answer/95876101 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 以默认的 innodb 存储引擎为例:做为主键时,uuid和自增相比较,自增更适合。原因:1 uuid是无序的, 插入数据时,页的位置会发生变化,页分裂,速度慢。 2 uuid占的空间大,并且innodb中,别的索引还都要包含主键的值,那么每个索引的空间也都会增大,占的空间大,需要读数据时一般会认为需要的io次数多。 作者:河南-老宋 链接:https://www.zhihu.com/question/43500172/answer/113356943 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 innodb 中的主键是聚簇索引,会把相邻主键的数据安放在相邻的物理存储上。如果主键不是自增,而是随机的,那么频繁的插入会使 innodb 频繁地移动磁盘块,而影响写入性能。 作者:Java编程宇宙 链接:https://www.zhihu.com/question/43500172/answer/2285446787 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 因为 uuid 相对顺序的自增 id 来说是毫无规律可言的,新行的值不一定要比之前的主键的值要大,所以innodb无法做到总是把新行插入到索引的最后,而是需要为新行寻找新的合适的位置从而来分配新的空间。这个过程需要做很多额外的操作,数据的毫无顺序会导致数据分布散乱,将会导致以下的问题:1)写入的目标页很可能已经刷新到磁盘上并且从缓存上移除,或者还没有被加载到缓存中,innodb在插入之前不得不先找到并从磁盘读取目标页到内存中,这将导致大量的随机IO2)因为写入是乱序的,innodb不得不频繁的做页分裂操作,以便为新的行分配空间,页分裂导致移动大量的数据,一次插入最少需要修改三个页以上3)由于频繁的页分裂,页会变得稀疏并被不规则的填充,最终会导致数据会有碎片在把随机值 (uuid和雪花id)载入到聚簇索引(innodb默认的索引类型)以后,有时候会需要做一次OPTIMEIZE TABLE来重建表并优化页的填充,这将又需要一定的时间消耗。结论:使用innodb应该尽可能的按主键的自增顺序插入,并且尽可能使用单调的增加的聚簇键的值来插入新行2.3 使用自增 id 的缺点那么使用自增的id就完全没有坏处了吗?并不是,自增id也会存在以下几点问题:1)别人一旦爬取你的数据库,就可以根据数据库的自增id获取到你的业务增长信息,很容易分析出你的经营情况2)对于高并发的负载,innodb在按主键进行插入的时候会造成明显的锁争用,主键的上界会成为争抢的热点,因为所有的插入都发生在这里,并发插入会导致间隙锁竞争3)Auto_Increment锁机制会造成自增锁的抢夺, 有一定的性能损失 附:Auto_increment的锁争抢问题,如果要改善需要调优innodb_autoinc_lock_mode 的配置 https://www.zhihu.com/question/43500172 http://www.cnblogs.com/tintown/archive/2005/03/02/111459.html 数据库主键设计之思考 在我们的数据库设计中,不可逃避的就是数据库表的主键,可能有很多朋友没有深入思考过,主键的设计对整个数据库的设计影响很大,因此我们不得不要重视起来。 主键的必要性: 有些朋友可能不提倡数据库表必须要主键,但在我的思考中,觉得每个表都应该具有主键,不管是单主键还是双主键,主键的存在就代表着表结构的完整性,表的记录必须得有唯一区分的字段,主键主要是用于其他表的外键关联,本记录的修改与删除,当我们没有主键时,这些操作会变的非常麻烦。 主键的无意义性: 我强调主键不应该具有实际的意义,这可能对于一些朋友来说不太认同,比如订单表吧,会有"订单编号"字段,而这个字段呢在业务实际中本身就是应该具有唯一性,具有唯一标识记录的功能,但我是不推荐采用订单编号字段作为主键的,因为具有实际意义的字段,具有"意义更改"的可能性,比如订单编号在刚开始的时候我们一切顺利,后来客户说"订单可以作废,并重新生成订单,而且订单号要保持原订单号一致",这样原来的主键就面临危险了。因此,具有唯一性的实际字段也代表可以作为主键。因此,我推荐是新设一个字段专门用为主键,此主键本身在业务逻辑上不体现,不具有实际意义。而这种主键在一定程序增加了复杂度,所以要视实际系统的规模大小而定,对于小项目,以后扩展不会很大的话,也查允许用实际唯一的字段作主键的。 ...

2015-03-04 · 3 min · 443 words · -

表的主键应当不具有任何业务含义

表的主键应当不具有任何业务含义 http://blog.sina.com.cn/s/blog_8020e4110101befz.html 表的主键应当不具有任何业务含义 (2012-12-17 15:10:36)转载▼ 标签: it 分类: DB/SQL 表的主键应当不具有任何业务含义 表通过主键来保证每条记录的唯一性,表的主键应当不具有任何业务含义,因为任何有业务含义的列都有改变的可能性。关系数据库学的最重要的一个理论就是: 不要给关键字赋予任何业务意义。假如关键字具有了业务意义,当用户决定改变业务含义,也许他们想要为关键字增加几位数字或把数字改为字母,那么就必须修改相关的关键字。一个表中的主关键字有可能被其他表作为外键。就算是一个简单的改变,譬如在客户号码上增加一位数字,也可能会造成极大的维护上的开销。 为了使表的主键不具有任何业务含义,一种解决方法是使用代理主键,例如为表定义一个不具有任何业务含义的ID字段 (也可以叫其他的名字) ,专门作为表的主键。 ——孙卫琴《精通Hibernate: Java对象持久化技术详解 本文来自CSDN博客,转载请标明出处: http://blog.csdn.net/jackie_lee/archive/2006/08/01/1007948.aspx ======================================= 昨天令狐因为处理动网论坛的数据库时,发现它是用帖子号来作为主键,由于无意中对它作了一些修改,导致帖子的关联变得混乱了。于是我们讨论了一下数据库表中主键的选择问题。因为对动网论坛的程序不熟,所以我也不知道它是怎么设计实现的,今天令狐把JavaEye上的一个关于这个方面的话题拿来讨论就好办了。 我起初也觉得用一个无意义的逻辑主键是一个好办法,至少说用一个字段就可以唯确定一条记录,使用上会很方便,速度应该也会快些。但是看了JavaEye那个帖里的讨论,以及在QQ群里的讨论后,我发现不完全是这样的。 其实这是两种不同的设计思路,谈不上用逻辑主键一定比用业务主键好。 用业务主键是传统的C/S应用开发的思路,包括我现在用的SAP里,也大量使用业务主键。但如果用O/R Mapping,则可能用逻辑主键好一些。 因 为对于传统C/S应用来说,以典型的两层结构看,前端处理的是一个数据表示的工作,后端处理的是一个数据持久化的工作。业务逻辑分散在两端,特别是在后 端。因为需要在后端通过Stored Procedure和View等来实现业务逻辑,应用直接与关系数据库打交道,所以数据的记录不但要求便于程序访问,对开发者来说,还要易读。也就是说需 要数据库的关系逻辑能够清晰地表达出业务逻辑来。主键采用业务主键是自然甚至是必须的。 而ORM应用恰恰相反。它需要一个最简单的 办法来标记一条唯一记录,但不需要有具体的意义,就像在OOP中,我们访问一个Object总是通过指针 (或相似的引用) ,但我们并不需要知道这个指针具 体的值是0x89ABCDEF还是0xFEDCBA98。逻辑主键就相当于一个指针,当别的关联表引用到这条记录时,用一个外键字段记录了这个逻辑主键, 就相当于那个Object中有一个属性记录了一个指向这个Object的指针。这时如果用业务主键-特别是复合业务主键-就是存心给自己打麻烦了。最 糟糕的情况就是当需要修改这个业务主键的值的时候,会导致所有的关联发生混乱-在传统C/S应用中,我们是用Trigger来解决这个问题,但是在 ORM中不可能这样做,否则那还要ORM干什么? 当然,对于开发者来说,在ORM这样的情况下,用逻辑主键存在一个至关重要的问题 就在于数据的可读性将要变差。也就是说,除非通过OO的视角来看数据才是易于理解的。但如果直接进入后端看关系数据库,将变得困难。因此,基本上,逻辑主 键与ORM是相辅相成的,缺一不可,并且采用ORM的开发者要尽可能避免与后端的关系数据打交道,否则就会非常的痛苦。 正如令狐所作的总结: 一个是从OO角度看,一个是直接深入数据库内部看。 关于数据库表应该采用逻辑主键还是业务主键的讨论 ============================= 数据库主键不应该具有任何业务意义 关系数据库学的最重要的一个理论是: 不要给关键字赋予任何业余意义。假如关键字具有了业务意义,当用户决定业务含义,也许他们想要为关键字增加几位数字或者把数字改为字母,那么就必须修改相关的关键字。一个表中的主关键字有可能被其他表做为外键。就算是一个简单的改变,也可能会造成极大的维护上的开销。 为了使表的主键不具有任何业务意义,一种解决办法是使用代理主键,例如为表定义一个不具有任何业务含义的ID字段 (也可以叫其他名字) ,专门做为表的主键。 我回顾我以前设计的很多数据库,都在某些地方没有考虑周到,即使大部分的主键都没有业务意义,还是会有某些表的主键和业务联系起来。因为我一直认为,主键是用来保持唯一性的,之所以要有代理主键,是因为有一些记录的内容没办法保持唯一性。例如设计一个用户表,用户的名字有可能重复,这个人可能叫blue,那么人也可能叫blue。这样就需要一个ID来分清。 由于我之前的想法,导致我数据库设计上的一些错误。例如我曾经在一次数据库设计中使用一个ID来做为一个表的主键,该表是记录一些报表的。每个报表上都有一个ID,这个ID是具有业务意义的,是可以让客户输入,也可以自动生成的,但是客户说明这个ID是唯一的,是数字类型。因此由于它的唯一性,我在数据库中设计这个ID为数字类型的。但是到了后来客户要求使用文字类型的,例如原来的是"111111",他要求可以写成"11111A",“11111B”。这个时候由于这个ID做了很多表的外键,就会产生很多维护上面的麻烦。即使在数据库表之间做了级联更新和级联删除,修改数据类型还是很麻烦的事情。 这次RFID项目数据库设计我原来想使用RFID标签的ID做为产品的主键,因为RFID标签ID具有唯一性,使用它作为主键在查找的时候速度应该会快些。但是后来发现问题并不是这么简单。如果使用RFID标签ID做为主键,那么就具有了业务意义。当产品表和其他表关联,产品表的主键做为其他表的外键的时候,如果出现一些业务上的情况,例如RFID标签坏了,要更换,就会产生更改主键内容的问题了。 回顾一下,还是发现自己的基础不扎实。学习数据库的时候都不去上课。少年不努力,老大徒悲伤。 ==================================== 数据库中主键和外键的设计原则 主键和外键是把多个表组织为一个有效的关系数据库的粘合剂。主键和外键的设计对物理数据库的性能和可用性都有着决定性的影响。 必须将数据库模式从理论上的逻辑设计转换为实际的物理设计。而主键和外键的结构是这个设计过程的症结所在。一旦将所设计的数据库用于了生产环境,就很难对这些键进行修改,所以在开发阶段就设计好主键和外键就是非常必要和值得的。 主键: 关系数据库依赖于主键-它是数据库物理模式的基石。主键在物理层面上只有两个用途: 惟一地标识一行。 作为一个可以被外键有效引用的对象。 基于以上这两个用途,下面给出了我在设计物理层面的主键时所遵循的一些原则: 主键应当是对用户没有意义的。如果用户看到了一个表示多对多关系的连接表中的数据,并抱怨它没有什么用处,那就证明它的主键设计地很好。 主键应该是单列的,以便提高连接和筛选操作的效率。 注: 使用复合键的人通常有两个理由为自己开脱,而这两个理由都是错误的。其一是主键应当具有实际意义,然而,让主键具有意义只不过是给人为地破坏数据库提供了方便。其二是利用这种方法可以在描述多对多关系的连接表中使用两个外部键来作为主键,我也反对这种做法,理由是: 复合主键常常导致不良的外键,即当连接表成为另一个从表的主表,而依据上面的第二种方法成为这个表主键的一部分,然,这个表又有可能再成为其它从表的主表,其主键又有可能成了其它从表主键的一部分,如此传递下去,越靠后的从表,其主键将会包含越多的列了。 永远也不要更新主键。实际上,因为主键除了惟一地标识一行之外,再没有其他的用途了,所以也就没有理由去对它更新。如果主键需要更新,则说明主键应对用户无意义的原则被违反了。 注: 这项原则对于那些经常需要在数据转换或多数据库合并时进行数据整理的数据并不适用。 ...

2014-05-28 · 1 min · 83 words · -

DB 事务

DB 事务 事务(Transaction): 是并发控制的单元,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。通过事务,sql server 能将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性。事务通常是以begin transaction开始,以commit或rollback结束。Commint表示提交,即提交事务的所有操作。具体地说就是将事务中所有对数据的更新写回到磁盘上的物理数据库中去,事务正常结束。Rollback表示回滚,即在事务运行的过程中发生了某种故障,事务不能继续进行,系统将事务中对数据库的所有已完成的操作全部撤消,滚回到事务开始的状态。 1、事务的特性 (ACID): 原一隔持 原子性 (Atomic) : 即事务是不可分割的最小工作单元,事务内的操作,要么全部执行,要么全部不执行。 一致性 (Consistency) : 事务在完成时,必须是所有的数据都保持一致状态。 在事务执行前数据库的数据处于正确的状态,而事务执行完成后数据库的数据还是处于正确的状态,即数据完整性约束没有被破坏;如银行转帐,A转帐给B,必须保证A的钱一定转给B,一定不会出现A的钱转了但B没收到,否则数据库的数据就处于不一致 (不正确) 的状态。 隔离性 (Isolation) : 一个事务的执行不能被其他事务所影响。 并发事务执行之间无影响,在一个事务内部的操作对其他事务是不产生影响,这需要事务隔离级别来指定隔离性; 事务必须是互相隔离的,防止并发读写同一个数据的情况发生 。 持久性 (Durable) : 一个事务一旦提交,事物的操作便永久性的保存在DB中。即使此时再执行回滚操作也不能撤消所做的更改。 事务类型 数据库事务类型有本地事务和分布式事务: 本地事务: 就是普通事务,能保证单台数据库上的操作的ACID,被限定在一台数据库上; 分布式事务: 涉及两个或多个数据库源的事务,即跨越多台同类或异类数据库的事务 (由每台数据库的本地事务组成的) ,分布式事务旨在保证这些本地事务的所有操作的ACID,使事务可以跨越多台数据库; Java事务类型有JDBC事务和JTA事务: JDBC事务: 就是数据库事务类型中的本地事务,通过Connection对象的控制来管理事务; JTA事务: JTA指Java事务API(Java Transaction API),是Java EE数据库事务规范, JTA只提供了事务管理接口,由应用程序服务器厂商 (如WebSphere Application Server) 提供实现,JTA事务比JDBC更强大,支持分布式事务。 Java EE事务类型有本地事务和全局事务: 本地事务: 使用JDBC编程实现事务; 全局事务: 由应用程序服务器提供,使用JTA事务; 按是否通过编程实现事务有声明式事务和编程式事务; 声明式事务: 通过注解或XML配置文件指定事务信息; 编程式事务: 通过编写代码实现事务。 隐式事务: 当连接以隐式事务模式进行操作时,sql server数据库引擎实例将在提交或回滚当前事务后自动启动新事务。无须描述事物的开始,只需提交或回滚每个事务。但每个事务仍以commit或rollback显式结束。连接将隐性事务模式设置为打开之后,当数据库引擎实例首次执行下列任何语句时,都会自动启动一个隐式事务: alter table,insert,create,open ,delete,revoke ,drop,select, fetch ,truncate table,grant,update在发出commit或rollback语句之前,该事务将一直保持有效。在第一个事务被提交或回滚之后,下次当连接执行以上任何语句时,数据库引擎实例都将自动启动一个新事务。该实例将不断地生成隐性事务链,直到隐性事务模式关闭为止。 ...

2014-05-21 · 5 min · 898 words · -

JDBC URL

JDBC URL disable tls JDK8版本过高引起MySQL连接失败:javax.net.ssl.SSLHandshakeException: No appropriate protocol https://juejin.cn/post/6969142310718144520 jdbc:mysql://127.0.0.1/database0?useunicode=true&characterencoding=utf8&tinyInt1isBit=false&useSSL=false MySQL MySQL Connector/J Driver 驱动程序包: http://mvnrepository.com/artifact/MySQL/MySQL-connector-java 驱动程序类名: com.MySQL.jdbc.Driver JDBC URL Format The general format for a JDBC URL for connecting to a MySQL server is as follows, with items in square brackets ([ ]) being optional: jdbc:MySQL://[host1][:port1][,[host2][:port2]]…[/[database]] [?propertyName1=propertyValue1[&propertyName2=propertyValue2]…] Here is a simple example for a connection URL: jdbc:MySQL://localhost:3306/sakila?profileSQL=true JDBC URL: jdbc:MySQL://:/<database_name> 默认端口3306,如果服务器使用默认端口则port可以省略 ...

2014-03-05 · 2 min · 332 words · -

H2 Database

H2 Database H2的简单使用 H2不依赖与任何Jar包,使用H2时,只需要将H2的Jar包添加到classpath中即可。 Xml代码 <img alt="收藏代码" src="http://puroc.iteye.com/images/icon_star.png" /> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.3.171</version> </dependency> **配置数据源: ** 通过spring jdbc来访问H2,下面是spring的配置,在这里我使用的是H2的in-memery模式。 Xml代码 <img alt="收藏代码" src="http://puroc.iteye.com/images/icon_star.png" /> <bean id="dataSource4H2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="org.h2.Driver" /> <property name="url" value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;IGNORECASE=TRUE;MODE=MySQL" /> <property name="username" value="test" /> <property name="password" value="test" /> </bean> <bean id="jdbcTemplate4H2" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"> <ref bean="dataSource4H2" /> </property> </bean> H2的URL可以支持很多参数的设置,具体可以参看H2的官方网站http://www.h2database.com/html/features.html 我这里的参数配置说明如下: a) jdbc:h2:mem:test: 代表用内存来存储数据。mem:后面的为数据库名称。 b) DB_CLOSE_DELAY=-1: 代表当JVM停止时才关闭H2数据库。 c) IGNORECASE=TRUE: 不区分大小写。 d) MODE=MySQL: H2本身支持的是标准的SQL,但实际上不同的数据库之间存在一些差别,H2为了适配不同的数据库,可以在URL中添加MODE这个参数,我们使用的是MySQL数据库,所以MODE=MySQL ...

2014-02-21 · 1 min · 93 words · -

Navicat

Navicat 一套适用于MySQL数据库系统地图形化数据库管理、报告以及监控的工具。新版本具有高性能的、具有商业智能的、强大的备份功能,此外还有许多的改进。含简体中文文件。 官方网站: www.navicat.com 官方下载地址: http://www.navicat.com/en/products/navicat_MySQL/MySQL_overview.html中文下载地址: http://down.chinaz.com/soft/22655.htm

2014-01-15 · 1 min · 7 words · -

Database – DDL,DML,DCL,TCL

Database – DDL,DML,DCL,TCL DDL (Data Definition Language) 数据库定义语言statements are used to define the database structure or schema. DDL是SQL语言的四大功能之一。 用于定义数据库的三级结构,包括外模式、概念模式、内模式及其相互之间的映像,定义数据的完整性、安全控制等约束 DDL不需要commit. CREATE ALTER DROP TRUNCATE COMMENT RENAME DML (Data Manipulation Language) 数据操纵语言statements are used for managing data within schema objects. 由DBMS提供,用于让用户或程序员使用,实现对数据库中数据的操作。 DML分成交互型DML和嵌入型DML两类。 依据语言的级别,DML又可分成过程性DML和非过程性DML两种。 需要commit. SELECT INSERT UPDATE DELETE MERGE CALL EXPLAIN PLAN LOCK TABLE 3.DCL (Data Control Language) 数据库控制语言 授权,角色控制等 GRANT 授权 REVOKE 取消授权 4.TCL (Transaction Control Language) 事务控制语言 SAVEPOINT 设置保存点 ...

2012-07-01 · 2 min · 400 words · -

Derby

Derby Apache Derby, an Apache DB subproject, is an open source relational database implemented entirely in Java and available under the Apache License, Version 2.0. Some key advantages include: Derby has a small footprint - about 2.6 megabytes for the base engine and embedded JDBC driver. Derby is based on the Java, JDBC, and SQL standards. Derby provides an embedded JDBC driver that lets you embed Derby in any Java-based solution. ...

2011-09-22 · 2 min · 271 words · -