数据专栏

智能大数据搬运工,你想要的我们都有

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

「深度学习福利」大神带你进阶工程师,立即查看>>>
简介
时序时空数据库(Time Series & Spatial Temporal Database,简称 TSDB)是一种高性能、低成本、稳定可靠的在线时序时空数据库服务,提供高效读写、高压缩比存储、时序数据插值及聚合计算等服务,广泛应用于物联网(IoT)设备监控系统、企业能源管理系统(EMS)、生产安全监控系统和电力检测系统等行业场景;除此以外,还提供时空场景的查询和分析的能力。
三个数据库
时序时空数据库文档最近经过几次大的变动,有点乱,看的时候注意一下。
时序数据库TSDB版
经过阿里集团大规模验证的时序数据库,支持分布式集群架构水平扩展,支持千万物联网设备接入,基于自研压缩算法,具备高效压缩比。 - 针对时序数据优化,包括存储模型,多值数据模型,时序数据压缩、聚合、采样,高效压缩算法,列存,边缘一体化; - 具备高性能,内存优先数据处理,分布式MPP SQL并行计算,动态schema,实时流式数据计算引擎,海量时间线自适应索引; - 高可扩展,数据动态分区,水平扩展,动态弹性扩容,动态升降配规格;高可靠性,自动集群控制,线程级读写分离,多层数据备份,分级存储; - 瞄准的是大规模指标数据,事件数据场景
协议兼容OpenTSDB,但后面内核实现是阿里自研的。但还是完全可以把它当作OpenTSDB的阿里云版,参见 相比OpenTSDB优势
InfluxDB®
不仅仅是一个数据库,更是一个监控系统,围绕采集,可视化,分析服务,事件和指标存储和计算系统;走的是tick生态,瞄准指标,事件,trace,日志,实时分析场景。
InfluxDB®刚上线不久,现在还处在公测阶段。写入速度经测试,每次500条数据,每秒可以执行26次左右,平均速度达到1万/s,增加每次写入数据条数应该还能提高速度。另外,请求地址是外网,如果使用vpc网络速度应该还会加快不少。
注意:InfluxDB在阿里云上有时间线限制(数据库级别最高1万),时间线的定义参见后面简介。
时空数据库
时空数据库能够存储、管理包括时间序列以及空间地理位置相关的数据。时空数据是一种高维数据,具有时空数据模型、时空索引和时空算子,完全兼容SQL及SQL/MM标准,支持时空数据同业务数据一体化存储、无缝衔接,易于集成使用。
时空数据库主要是空间相关的场景,比如热力图,店铺选址等等。
时序数据库简介(主要是InfluxDB)
时序数据库英文全称为 Time Series Database,提供高效存取时序数据和统计分析功能的数据管理系统。主要的时序数据库包括OpenTSDB、Druid、InfluxDB以及Beringei这四个。本人主要了解一点OpenTSDB和InfluxDB,不过时序数据库有很多共性。
基本名词
measurement: tag,field和time列的容器 对InfluxDB: measurement在概念上类似于传统DB的table(表格) 从原理上讲更像SQL中表的概念,这和其他很多时序数据库有些不同 对其他时序DB: Measurement与Metric等同
field(数值列): TSDB For InfluxDB®中不能没有field。 注意:field是没有索引的 在某种程度上,可以把field理解为k/v表的value
tag(维度列): tag不是必须要有的字段 tag是被索引的,这意味着以tag作为过滤条件的查询会更快 在某种程度上,可以把field理解为k/v表的key
timestamp(时间戳): 默认使用服务器的本地时间戳 时间戳是UNIX时间戳,单位:纳秒 最小的有效时间戳是-9223372036854775806或1677-09-21T00:12:43.145224194Z 最大的有效时间戳是9223372036854775806或2262-04-11T23:47:16.854775806Z
point(数据点): 由时间线(series)中包含的field组成。每个数据点由它的时间线和时间戳(timestamp)唯一标识 您不能在同一时间线存储多个有相同时间戳的数据点
Series(时间线)
Series是InfluxDB中最重要的概念,时序数据的时间线就是:一个数据源采集的一个指标随着时间的流逝而源源不断地吐出数据这样形成的一条数据线称之为时间线。
下图中有两个数据源,每个数据源会采集两种指标: Series由Measurement和Tags组合而成, Tags组合用来唯一标识Measurement 就是说: 1. Measurement不同,就是不同的时间线 2. Measurement相同,Tags不同也是不同的时间线
retention policy(保留策略,简称RP)
一个保留策略描述了: 1.InfluxDB保存数据的时间(DURATION) 2.以及存储在集群中数据的副本数量(REPLICATION) 3.指定ShardGroup Duration 注:复本系数(replication factors)不适用于单节点实例。 autogen:无限的存储时间并且复制系数设为1
RP创建语句如下: CREATE RETENTION POLICY ON ON DURATION REPLICATION [SHARD DURATION ] [DEFAULT] 实例: CREATE RETENTION POLICY "one_day_only" ON "water_database" DURATION 1d REPLICATION 1 SHARD DURATION 1h DEFAULT
写入时指定rp进行写入: % 如果没有指定任何RP,则使用默认的RP curl -X POST 'http://localhost:8086/write?db=mydb&rp=six_month_rollup' --data-binary 'disk,host=server01 value=442221834240i 1435362189575692182'
Shard Group
Shard Group是InfluxDB中一个重要的逻辑概念: Shard Group会包含多个Shard,每个Shard Group只存储指定时间段的数据 不同Shard Group对应的时间段不会重合
每个Shard Group对应多长时间是通过Retention Policy中字段”SHARD DURATION”指定的: 如果没有指定,也可以通过Retention Duration(数据过期时间)计算出来,两者的对应关系为: Retention Duration SHARD DURATION <2 days 1h >=2days and <=6month 1day >6month 7day
Shard: 类似于HBase中Region,Kudu中Tablet的概念 1. Shard是InfluxDB的存储引擎实现,具体称之为TSM(Time Sort Merge Tree) Engine 负责数据的编码存储、读写服务等。 TSM类似于LSM,因此Shard和HBase Region一样包含Cache、WAL以及Data File等各个组件, 也会有flush、compaction等这类数据操作 2. Shard Group对数据按时间进行了分区 InfluxDB采用了Hash分区的方法将落到同一个Shard Group中的数据再次进行了一次分区 InfluxDB是根据hash(Series)将数据映射到不同的Shard,而非根据Measurement进行hash映射
InfluxQL
行协议
格式: [,=[,=]] =[,=] []
以下是符合格式的数据写入TSDB For InfluxDB®的示例: 1. cpu,host=serverA,region=us_west value=0.64 2. payment,device=mobile,product=Notepad,method=credit billed=33,licenses=3i 1434067467100293230 3. stock,symbol=AAPL bid=127.46,ask=127.48 4. temperature,machine=unit42,type=assembly external=25,internal=37 1434067467000000000
登录 // 登录 $> influx -ssl -username <账号名称> -password <密码> -host <网络地址> -port 3242 // 创建用户 > create user gordon with password '1QAZ2wsx' // 赋值权限 grant all privileges to gordon // 创建数据库 create database testdb
基本QL 1. # 显示时间线 show series 2. # 显示度量 show measurements 3. # 显示Tag的Key show tag keys 4. # 显示数据字段的Key show field keys
查询: 1. select * from metrics 2. show tag keys from metrics 3. show field keys from metrics # 查看自定度量的数据, 里面的相关字段,官方建议使用“双引号”标注出来 select * from "CPU" order by time desc # 查看指定的Field和Tag select "load1","role" from "CPU" order by time desc # 只查看Field select *::field from "CPU" # 查询指定Tag的数据,注意,Where子句的字符串值要使用“单引号”,字符串值 # 如果没有使用引号或者使用了双引号,都不会有任何值的返回 select * from "CPU" where role = 'FrontServer' # 查询Field中,load1 > 20 的所有数据 select * from "CPU" where "load1" > 20
插入: INSERT weather,location=us-midwest temperature=82 1465839830100400200
基本运算: # 执行基本的运算 select ("load1" * 2) + 0.5 from "CPU" // SELECT语句支持使用基本的数学运算符,例如,+、-、/、*和()等等。 SELECT field_key1 + field_key2 AS "field_key_sum" FROM "measurement_name" WHERE time < now() - 15m SELECT (key1 + key2) - (key3 + key4) AS "some_calculation" FROM "measurement_name" WHERE time < now() - 15m // 使用聚合函数计算百分比: SELECT (sum(field_key1) / sum(field_key2)) * 100 AS "calculated_percentage" FROM "measurement_name" WHERE time < now() - 15m GROUP BY time(1m)
作者:新溪
原文链接 ​
本文为云栖社区原创内容,未经允许不得转载。
数据库
2019-05-27 13:14:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
表命名规范
表命名的规则分为3个层级,层级之间通过 _ 分割,例如 b_r_identity 、 d_l_identity 。规约为: [leavel]_[type]_[name]
[leavel] 表示数据库表的层级和功能,分为: s :业务无关的系统数据表。 d :业务字典表。 b :基础业务表。 v :视图。 i :聚合中间表。
[type] 表示数据库表的类型,分为: r :行数据表。 l :列数据表。 g :分组数据表。
[name] 用来表示表的作用名称,由于mysql默认对大小写不敏感,采用下划线命名法。比如: identity_enterprise 。
因此,综合上面的规范,如果将 用户模块 命名为 user ,相关的表命名为: 数据字典以列数据的方式存储,可以命名为: d_l_user_dc 。 用户主表以行数据的方式存储,命名为: b_r_user 。 用户账户表: b_r_user_account 。
采用以上命名法的目的: 便于代码开发阶段区分表的功能和数据组织形式; 通过前缀为以后可能会引入的开源框架生成的表扩展命名空间。 比如引入了流程框架activity,会向数据库添加几十个表,其中有名为account的表,如果不适用前缀,会增加引入的成本。
字段命名规范 逻辑主键:id。所有的表必须创建逻辑主键。采用统一的主键便于分库分表以及数据抽取。 业务主键:code, 确保唯一性或联合主键。业务主键除了反映真实数据关联,也便于程序进行类型判断。 外键:columnName_fk,字段信息名+fk后缀,比如state_fk。 父主键关联:pid
行数据规范
所有的表必须包含modify_date、modify_type、modify_user、modify_access_id、activity字段。 modify_date :标记数据修改时间,用于数据增量ETL或缺陷回溯。类型: TIMESTAMP(13) 。 modify_type :数据修改类型,通常数据由运营后台修改 OPR(0) ,或账号拥有这修改 USR(1) 。用于记录数据修改的行事人。类型: TINYINT(1) 。 modify_user :结合modify_type,标记是修改人。类型: BIGINT 。 modify_access_id :在数据库中用于标记当前数据修改是由哪个访问id导致的。类型: BIGINT 。 所有的时间字段均以时间戳(Java十三位标准)的方式存储,Mysql对应 TIMESTAMP(13) 类型。
ER范式规范与反范式规范
ER三范式
在联机事物数据库中(Mysql的InnoDB类型数据库)业务数据与业务数据(命名以 b 开头的表)之间的ER关系严格按照ER三范式进行设计: 三范式原则: 1. 有逻辑主键、主键非空、主键唯一、字段不可再分。 2. 具备独立不依赖数据内容的逻辑主键。 3. 没有属性传递(不能有数据冗余)
反范式适用范围
业务字典允许数据传递
业务数据( b 开头)与数据字典( d 开头)之间的依赖关系允许数据冗余(传递)。
满足以上条件必须保证业务字典数据演进严格依赖 开闭原则 :类似设计模式的开闭原则——数据修改关闭,数据添加开放。
这个时候可以在业务数据表中对业务字典进行数据冗余,例如:
字典:
id pid code name ...
主键
父主键
业务编码
名称

数据表:
id state_fk state_code state_name ...
主键
父外键
状态编码
状态名称
...
数据仓库或视图完全反范式
数据仓库(MyISam)或者事物数据库(InnoDB)中的视图和数据中间表优先使用反范式的规则去实现。
参考阅读
关于范式设计的说明请参阅后文的**“ER范式与反范式设计规范设计背景及原因”**。
主键规范
逻辑(物理)主键使用64bit的 BigInt 类型,通过 Snowflake算法获取 。它可以完全充当 Mysql 主键,也能平滑兼容 MyCat 、 Sharding-jdbc (3.0后更名为 Sharding-Sphere )等开源分库分表数据源管理工具。
业务组件原则上不做任何关联查询,只用于标记单表业务内容。
采用该规范的原因请见后文 主键规范设计背景及原因 。
数据缓存规范
缓存通过Redis实现。
key使用规范
对应数据结构必须是扁平的(更像一个反范式的数据仓库表或视图)。由于在设计数据主键时保证主键id的全系统唯一性,理论上Nosql中key使用主键即刻确保唯一,但是为了区分业务,需要使用前缀。
索引数据使用模块+业务名+key:{module}:{buss}:{key} ,例如 SET user:mgr:1234567891234567891
原则上key的长度不能超过64个字符。太长的业务key请使用hash进行一次签名。
主数据与业务主键索引
主数据 :是指真实存储数据的结构。通常 对象 都是Redis中的HASH格式存储(HASH格式相当于Java中的map、Python中的dict、Json中的对象块——{}),功能数据数据根据需要使用string、set或list。
业务主键索引 :在我们使用key-value进行数据存储时,用于查询的key并无法满足业务,有时候数据是用业务主键传参的,这个时候需要创建一个指向真实主数据的索引,建立业务主键和逻辑主键的关联关系。这个时候在Redis中可以使用业务索引映射主数据key然后再取值的方式,比如下列格式: SET {module}:{buss}:{code} {module}:{buss}:{id} set hkey {module}:{buss}:{id} id 123 name "Alice" age 20
这样,业务主键code通过2次索引可以找到id对应的主数据。
Value数据规范
Java中的实体对象使用Redis中的HASH格式存储,确保数据的扁平化,不能使用嵌套结构。例如 //正确 id:{ name:"Alice", age:28, pos:"developer" salary:100000 } //错误 id:{ baseInfo:{ name:"Alice" age:28 }, workInfo:{ pos:"developer", salart:100000 } }
其他应用场景可以根据需要使用Set、List、String,请注意他们的差异(与Java对应的数据结构类似),并且一定保证数据扁平。
数据读写规范 当需要批量读写数据时,使用mset、mget等原生批量处理命令,Redis自动保证数据原子性。 尽量不要使用通道——pipeline。 不要使用Redis做事务处理。 禁止线上使用keys、flushall、flushdb等,管理员redis的rename机制禁掉命令。(严重影响性能)
参考资料:Redis更多的规范参考 阿里云Redis服务使用规范 。
主键规范设计背景及原因。
在分布式微服务系统中采用Mysql的自增主键在分表分库、灾备合库、分布式执行、缓存Write-Behind写时会有很大制约,因此需要制定不依赖数据库的行主键规范。
主键类型
在解释数据设计规范之前先理解 物理主键 、 逻辑主键 和 业务主键 的区别:
物理主键 即认为是数据库的自身的物理标识主键,例如oracle的ROW_ID,mysql的自增Sequence,物理主键除了具备独立的物理特性,也是数据库连接数据的核心。mysql中要求单表唯一。
逻辑主键 是与数据库无关的非业务意义的主键,用于对行数据的唯一性进行标识。在单数据库系统中,通常不需要逻辑主键,而在分布式系统中,逻辑主键的意义重大。无论是什么数据库,逻辑主键要求全库(所有的数据库)唯一。某些时候可以将物理主键和逻辑主键合二为一。
业务主键 是指与含有业务特性的的主键,例如订单编号会以 时间+流水号+业务编号实行存在。业务主键通常的要求是单向业务唯一,由于从技术角度来说业务是随时可变的,因此业务主键并不能提到逻辑主键或物理主键。
MySql(InnoDB)索引特性
由于InnoDB的行数据排列是以主键数据(Oracle是ROW_ID)作为b+树索引, 而扩展的索引都以主键索引作为数据对象——这种方式称为聚集索引 。所以最大效率的保证b+树主键和索引数据进入的递增性对于数据库的性能有决定性作用(b+树越扁平,效率越高)。
使用mysql的自增Sequence可以很自然的解决这个问题,主键就向一个队列一样,只要insert数据向队列尾push数据即可,几乎不会发生索引重建和数据碎片。但是自增队在分布式系统中使用有巨大的局限性。
如果直接使用UUID既充当物理主键又充当业务主键,由于 UUID并无法保障数据的递增性(?) ,会导数据碎片已经主键索引更新效率。此外UUID的长度是32位字符串,即使用ascii的编码方案,也会占据不少的空间。
传统中间解决方案
基于Mysql目前也可以自动生成UUID,所以有一种中间解决方案是在分布式系统的数据库中物理主键使用Mysql的自增Sequence,逻辑主键使用UUID,所有的ER关联都使用UUID建立,这样可以很好的保障 聚集索引 添加数据的效率,且能极大减少碎片。由于InnoDB聚集索引除了主键索引都会引起二次查询,所以这种方式外关联效率较差(即使是单表查询效率也一般)。
主键需求
整合以上内容,现在我们需要一个具备以下特征的主键: 递增。 全系统唯一(至少保证单业务唯一)。 高效产生。 尽量短。(减少扩展索引的存储空间)
连续递增与趋势递增
对于B+树递增要求的并不需要连续递增(0,1,2,3,4......),只要趋势递增即可(0,3,5,7,18,100.....)。
Snowflake算法
为了满足主键需求,现在比较推崇的是 Snowflake算法 。
Snowflake算法会产生一个 64bit 的数据,正好在Java中是一个long类型,对应Mysql是一个BigInt类型。 第一位是符号位(正负号)。在使用过程中基本不用理睬。 其后的41位表示时间戳的差值。 10位工作机id称为workid,需要人工指定。10bit=2^10=1024个Id 后续的12位用于在微秒级别生成序列号。
效率: 因为其本质上还是一个数字,所以在关联查询能力上不会比源生的自增Sequence的差多少(微秒/纳秒级别)。 官方文档Snowflake Id算法理论上单机每秒可以生成409.6万个ID——1000个微秒单位,12位序列编码=1000*(2^12)。
递增性质:
算法是以微秒+递增序列作为区分的,并且时间单位处于64bit中的高位,在所有的微服务节点没有达到生成极限时(每秒409.6万个)一定是趋势递增的,计时达到了极限,也仅仅在时间单位出现相同。
传输:
64bit的long类型转换为十进制只有20个数字,由于64bit的第一个位置表示符号,所以实际只有19个数字。在http报文中仅仅是19个字符。如果将其转换为16进制或[0~9a~z]满表的36进制。长度还能极大的压缩。
局限性: 由于其本质是基于微秒级的机器时间戳进行ID生成,所以当整个集群有时间一致性服务时候,可能会发生时间回拨(也有可能是人为修改,不过几乎不可能发生)。当时间发生回拨时就会有极大的概率在回拨时间区内出现主键冲突。百度有个Snowflake算法变种解决方案是使用中心化的按块生成ID尽可能的回避这个问题。此外如果并发并没有达到极高的程度时,可以让入口服务器来统一生成access_id作为后续业务新增数据时的主键,当然这也没法完全解决这个问题。 64bit的算法如果要求全系统主键唯一,那么基于算法的workid特性最大支持1024台服务器同时生成主键,再多就会出现冲突。解决办法就是不要求全系统唯一,而收敛为单个业务唯一,这样可以视为单个业务可以具有1024个分布式服务。 其数据位数决定了其从使用开始最多服务61年,61年后出现类似于千年虫的问题超出现有数据位。
参考 Snowflake算法最早由推特twitter的工程师创立并开源,现在整合到RPC框架 Finagle 中,当然没必要引入整个Finagle,可以到这里 下载核心算法 。 Snowflake有个非常方便的使用途径是引入 sharding-core 。然后使用其中的 SnowflakeShardingKeyGenerator 。当然Snowflake算法本身并不复杂,使用源码就能解决问题,而且具有极佳的扩展性。 算法中workid最大支持1024,通常可以通过主动命名、ip地址、服务器命名等方式决定。 网上关于Snowflake算法的极少很多,自行查询解决问题。
ER范式与反范式设计规范设计背景及原因
业务字典与代码适配器
通常情况下,在一个标准的联机事物系统中数据库和业务代码的关系可以总结为: 数据库的的作用就是存储业务数据和状态结论。 业务代码是为了处理数据从外部进入或数据库内部的状态迁移。
例如一个用户注册,通过代码各种处理和鉴权之后,最终会将用户的各种注册信息写入到数据库中。一个用户登录会涉及到数据库已经存在的数据的变更。
数据库可以看成一个静态的网状结构,只是忠实的在网状结构的某些点记录“结论”,结论通常由2部分组成:数据+状态。与之相对的,代码的作用就是接收外部信息后触发数据库中的状态迁移和数据演进。业务代码最困难的也是导致问题最多的就是状态控制与状态处理。
对于代码而言,处理各种状态是最常见的过程,例如: if(state = A){ do A processor }else if(state = B){ do B processor }
一个不规范的数据库状态的存储方式千差万别,例如一个用户信息表 user_info 有以下结构:
id name user_state ...
1 2
Alice Bob
0 1
... ...
现在有一个 user_state 字段表示用户状态,然后当值为0时表示注销、当值为1时候表示启用,或者还会有其他更多的状态不断添加进来。
这样会导致3个问题: 0和1并没有实际意义,在设计初期可能会很有意识的在字段备注中说明每个数字带边状态意义,但是在系统不断的进化或迭代后,0和1的控制难度会越来越大。 状态的不同必然会导致分支处理,分支处理最粗暴的方式就是上面的代码例子会进行if-else堆叠,随着状态的增加,整个系统的if-else块会飞速递增。 无论是否使用0和1还是有实际意义的单词标记状态。在理解的过程中要嵌入大量的if块去了解处理的结果,可读性很差。从而导致新加入项目的开发人员无暇去根据已有的状态阅读代码,而更趋向于增加状态而非在原来的状态上进行演进。这样会导致一个简单的业务标识状态的字段会越来越多。
基于以上原因,引入业务字典来解决这个问题。将上面的状态控制拆分为业务字典表和业务表。
业务字典表
code name ...
activity locked
账户启用 账户锁定
... ...
数据报表
id name user_state ...
1 2
Alice Bob
activity locked
... ...
//伪编码 interface Processor{ Result Do(Data data); } class Activity implements Processor{ public Result Do(Data data){ //DO } } class Locked implements Processor{ public Result Do(Data data){ //DO } } class AdapterFactory{ //写Java的请注意 //这里用js或Python的方式表示一个map结构(python中叫dict结构,js中叫对象结构) //只因用Java表示一个map太麻烦 Map processorDict = { "activity":Activity.instance, "locked":Locked.instance } public static getProcessor(enum state){ return processorDict[State]; } } //使用 Processor processor = AdapterFactory.getProcessor(state); processor.do(data);
使用以上方式。首先在业务流程中不必嵌套大量的if。其次可以将代码与业务字典的状态进行1-1绑定,即一个状态对应一个适配器。最后需要扩展更多的状态的就是对应扩展更多的处理器(适配器)。
咋一看这样的写法似乎比if多不少代码,但是用这种状态+适配器的模式在系统迭代时能够带来极大的便利。
数据仓库的反范式
严格按照ER三范式设计数据库带来的好处是能最好的反应真实业务,能及有效的约束数据强一致性避免“脏数据”的出现。带来的问题是大量的外关联导致大量的关联查询,严重影响查询性能。
因此建议如果某项业务启用了数据仓库(MyISam),或者在事物数据库(InnoDB)中使用了View或中间表集合数据,务必严格按照Kimball或Inmon模型使用反范式创立单体数据仓库表。
数据库
2019-05-27 00:19:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
用户初巡检,进入系统,登陆对方系统的CRT,是一个中文的crt,但是每次打开都会有个防火墙的错误提示,“数据库里没找到防火墙“无”。此会话将尝试不通过防火墙进行连接。”如下图:
出现这个错误的原因是在CRT里的数据库中没有找到防火墙的配置文件,我们需要在配置文件夹中添加这个配置文件。
解决:
找到CRT的菜单栏->选项->全局选项->常规,在最下面有个配置文件夹(E),这个就是配置文件夹的路径,
我的路径是C:\Documents and Settings\tstt\Application Data\VanDyke\Config复制下来,在资源管理器的路径中粘贴,
会发现这个文件夹中没有FireWalls这个文件夹,当然也就找不到防火墙 了,下面就是创建这个文件夹,并在文件夹中创建一个"无.ini"文件。
OK,再打开就没有这个错误提示了!
数据库
2019-05-26 17:17:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
视图是由数据库中的一个表或者多个表导出的虚拟表,方便用户操作。其内容是由查询定义。
视图是存储在数据库中的查询的sql语句。
一、创建视图
1. 查看创建视图的权限 select Select_priv,Create_view_priv from mysql.user where user='用户名' Select_priv : 表示是否具有select权限; Create_view_priv : 表示创建视图的权限;
2. 创建视图的步骤 create [ALGORITHM={UNDEFINED|MERGE|TEMPTABLE}] view 视图名[(属性清单)] as select 语句 [with [CASCADED|LOCAL] CHECK OPTION]; ALGORITION是可选参数,表示视图选择的算法 “视图名” 参数表示创建的视图名称 “属性清单” 是可选参数,指定视图中的各个属性的名词,默认从某个表中查出某些满足条件的记录 select属性 参数是一个完整的查询语句,表示从表中查出某些满足条件的记录,将这些记录导入视图中
二. 视图操作
1. 查看视图
1.1 DESCRIBE 语句 describe 视图名; desc 视图名;
这个和查普通表信息相同。
1.2 SHOW TABLE STATUS 语句 show table status like '视图名';
同样这个可以用在普通表上。查看表的构成信息。
1.3 SHOW CREATE VIEW 语句 show create view 视图名
可以查看视图的所有信息。
2. 修改视图
2.1 CREATE OR REPLACE VIEW create or replace [algorithm ={undefine|merge|temptable}] view 视图[(属性清单)] as select 语句 [with [cascaded |local] check option]
2.3 ALTER
3. 更新视图
一般企业中不允许直接更新视图。
4. 删除视图 drop view if exists<视图名> [restrict|cascade]
数据库
2019-05-26 16:43:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
一、索引的分类 普通索引 唯一性索引
unique约束设置唯一索引,主键是一种特殊的唯一索引。 全文索引
查询较大数据量时,使用全文索引可以提高查询速度。 单列索引
包括以上三个索引 多列索引 空间索引
二、创建索引
1. 在建立数据表时创建索引 create table table_name( 属性名 数据类型 [约束条件], ... 属性名 数据类型 [UNIQUE|FULLTEXT|SPATIAL] index|key [别名](s属性名[长度][ASC|DESC]) ); UNIQUE : 可选项,表明索引为唯一性索引。 FULLTEST : 可选项,表明索引为唯一性索引。 SPATIAL : 可选项,表明索引为空间索引。 index和key参数用于指定字段索引,在用户选择时,只需要选择其中一个即可;另外别名为可选项。其作用时给创建的索引取新的名称;别名的参数如下:
(1)属性名 :指索引对应的字段名称,该字段必须被预先定义。
(2)长度 :可选项,指索引的长度,必须是字符串类型才能使用。
(3)ASC/DESC :可选项,ASC表示升序排列,DESC参数表示降序排列。
2. 在已建立的数据表中建立索引 create [unique|fulltext|spatial] index index_name on table_name(属性[length][ASC|DESC]); index_name : 索引名称。 table_name : 指定创建索引的表名称。 可选参数 :指定索引类型。 属性参数 :指定索引对应的字段。 length : 指定索引长度。 ASC/DESC : 指定数据库表的排序顺序。
3. 修改数据表结构添加索引 alter table table_name add [unique|fulltext|spatial] index index_name(属性名[(length)[ASC|DESC]])
4. 删除所有 drop index index_name on table_name;
数据库
2019-05-26 16:08:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
1. 数学函数
函 数 作 用 ABS(x) 返回x的绝对值
CEIL(x),CEILIN(x) 返回不小于x的最小整数值
FLOOR(x) 返回不大于x的最大整数值
RAND() 返回0~1的随机数
RAND(x) 返回0~1的随机数,x值相同返回时返回的随机数相同
SIGN(x) 返回参数作为-1、0、1的符号,该符号取决于x的值为负、零或者正
PI() 返回圆周率PI,默认显示小数位数是7位,mysql内部会使用完全双精度值
TRUNCATE(x,y) 返回数值x保留到小数点后y位值
ROUND(x) 返回离x最近的整数
ROUND(x,y) 保留x小数点后y位的值,但截断时要进行四舍五入
POW(x,y),POWER(x,y) 返回x的y乘方的结果
SQRT(x) 返回非负数x的二次方根
EXP(x) 返回e(自然对数的底)的x乘方后的值
MOD(x,y) 返回x除以y以后的余数
LOG(x) 返回x的基数为2的对数
LOG10(x) 返回x的基数为10的对数
RADIANS(x) 将角度转换为弧度
DEGREES(x) 将弧度转换为角度
SIN(x) 返回x的正弦,其中x在弧度中被给定
ASIN(x) 返回x的反正弦,即正弦为x的值。x不在-1~1的话就返回null
COS(x) 返回x的余弦,其中x在弧度中被给定
ACOS(x) 返回x的反余弦,即余弦为x的值。x不在-1~1的话就返回null
TAN(x) 返回反正切值,即正切为x的值
ATAN(x),ATAN(x,y)
COT(x)
返回两个变量x及y的反正切。
返回x的余切
2. 字符串函数
函 数 作 用 CHAR_LENGTH(s) 返回字符串s的字符数(用于查询字符串长度)
LENGTH(s) 返回字符串的字节数
CONCAT(s1,s2..) 将几个字符串拼接起来,若一个为null则返回null
CONCAT_WS(x,s1,s2..) 同concat(s1,s2..)函数,但是每个字符串拼接的中要加上x
INSERT(s1,x,len,s2) 将字符串s2替换s1的x位置开始长度为len的字符串
UPPER(s),UCASE(s) 将字符串s的所有字母都变成大写
LOWER(s),LCASE(s) 将字符串s的所有字母都变成小写
LEFT(s,n) 返回字符串左边的n个字符串
RIGHT(s,n) 返回字符串右边的n个字符串
LTRIM(s) 返回去除了左边空格的s
RTRIM(s) 返回去除了右边空格的s
TRIM(s) 返回去除两边的空格的s
TRIM(s1 FROM s) 返回去除了两边s1的s
REPEAT(s,n) 将字符串s重复n次
SPACE(n) 返回n个空格
replace(s,s1,s2) 用s2代替s中的s1
STRCMP(s1,s2) 比较字符串s1和s2长度,s1长于s2则返回1,s2长于s1则返回-1,相等则返回0
SUBSTRING(s,n,len) 获取从字符串s的第n个位置开始长度为len的字符串
MID(s,n,len) 同SUBSTRING(s,n,len)
LOCATE(s1,s),POSITION(s1 IN s) 找到s中s1的位置
INSTER(s,s1) 查找字符串s1在s中的位置,返回首次出现位置的索引值
REVERSE(s) 将字符串s的顺序反过来
ELT(n,s1,s2) 返回第n个字符串
FIELD(s,s1,s2..)
FIND_IN_SET(s1,s2)
返回第一个与字符串s匹配的字符串的位置
返回在字符串s2中与s1匹配的字符串的位置
3. 日期和时间函数
函 数 作 用 CURDATE(),CURRENT_DATE() 返回当前时间
CURTIME(),CURRENT_TIME() 返回当前时间
NOW(),CURRENT_TIMESTAMP(),LOCALTIME(),SYSDATE(),LOCALTIMESTAMP() 返回当前日期和时间
UNIX_TIMESTAMP() 以unix时间戳形式返回当前时间
UNIX_TIMESTAMP(d) 将时间d以unix时间戳形式返回
FROM_UNIXTIME(d) 将unix时间戳的时间转换为普通格式的时间
UTC_DATE() 返回UTC日期
UTC_TIME() 返回UTC时间
MONTH(d) 返回日期d中的月份值,范围0~12
MONTHNAME(d) 返回日期d中的月份名称
DAYNAME(d) 返回日期d是星期几
DAYOFWEEK(d) 返回日期d是星期几,1是星期天,2是星期一
WEEKDAY(d) 返回日期d是星期几,0是星期一,1是星期二
WEEK(d) 计算日期d是本年的第几个星期,范围0~53
WEEKOFYEAR(d) 计算日期d是本年的第几个星期,范围1~53
DAYOFYEAR(d) 计算日期d是本年的第几天
DAYOFMONTH(d) 计算日期d是本月的第几天
YEAR(d) 返回年份值
QUARTER(d) 返回日期d是第几个季度,范围1~4
HOUR(t) 返回时间t中的小时值
MINUTE(t) 返回时间t中的分钟值
SECOND(t) 返回时间t中的秒钟值
EXTRACT(type of d) 从日期d中获取指定的值,type可以是YEAR,HOUR等
TIME_TO_SEC(t) 将时间t转换为秒
SEC_TO_TIME(s) 秒值s转换为时间格式
TO_DAYS(d) 计算d~0000年1月1日的天数
FROM_DAYS(n) 计算从0000年1月1日开始n天后的日期
DATEDIFF(d1,d2) 计算日期d1~d2之间相隔的天数
ADDDATE(d,n) 计算起始日期d加上n天的日期
SUBDATE(d,n) 计算起始日期d减去n天的日期
ADDTIME(t,n) 计算起始时间t加上n秒的时间
SUBTIME(t,n) 计算起始时间t减去n秒的时间
DATE_FORMAT(d,f) 按照表达式f的要求显示日期d
TIME_FORMAT(t,f)
GET_FORMAT(type,s)
按照表达式f的要求显示时间t
根据字符串s中获取type类型数据的显示格式
4. 条件判断函数
函 数 作 用 IF(expr,v1,v2) 如果表达式expr成立,则执行v1;否则执行v2
IFNULL(v1,v2) 如果v1不为空,则显示v1的值;否则显示v2的值
CASE WHEN expr1 THEN v1[WHEN expr2 THEN v2][ELSE vn]END
CASE expr WHEN e1 THEN v1[WHEN e2 THEN v2][ELSE vn]END
CASE表示函数开始,END表示函数结束。如果expr1成立,则返回v1的值。类似if(..)..else if(..)..else..
类似于switch..case v1:..break
5. 系统信息函数
函 数 作 用 示 例 VERSION() 获取数据库版本号 select VERSION();
CONNECTION_ID() 获取服务器的连接数 select CONNECTION_ID();
DATABASE(),SCHEMA() 获取当前数据库名 select DATABASE(),SCHEMA()
USER(),SYSTEM()_USER(),SESSION_USER(),CURRENT_USER() 获取当前用户 select USER();
CHARSET(str)) 获取字符串str的字符集 select CHARSET('mysql')
COLLATION(str)
LAST_INSERT_ID()
获取字符串str的字符排列顺序
获取最近生成的auto_increment值
select COLLATION('mysql')
select LAST_INSERT_ID()
6. 加密函数
函 数 作 用 示 例
PASSWORD(str) MD5(str)
对字符串str进行加密。经过次函数加密是不可逆的,其常常用于用户注册的密码加密 对字符串进行md5加密。经常用于对普通数据的加密
select PASSWORD('mysql'); select MD5('mysql');
7. 其他函数
函 数 作 用 FORMAT(x,n) 将数据进行格式化,将x保留到小数点后n位,四舍五入
ASCII(s) ASCII(s)返回字符串s的第一个字符的ASCII码
BIN(x) 返回x的二进制编码
HEX(x) 返回x的十六进制编码
OCT(x) 返回八进制编码
CONCV(x,f1,f2) 将数x从f1进制编程f2进制数
INET_ATION(IP)
INET_NTOA(N)
可以将IP地址转换为数字表示
可以将数字n转换成IP
数据库
2019-05-26 14:53:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
什么是主从复制
持久化保证了即使 redis 服务重启也会丢失数据,因为 redis 服务重启后会将硬盘上持久化的数据恢复到内存中,但是当 redis 服务器的硬盘损坏了可能会导致数据丢失,如果通过 redis 的主从复制机制就可以避免这种单点故障,如下图:

说明: 主 redis 中的数据有两个副本(replication)即从 redis1 和从 redis2,即使一台 redis 服务器宕机其它两台 redis 服务也可以继续提供服务。 主 redis 中的数据和从 redis 上的数据保持实时同步,当主 redis 写入数据时通过主从复制机制会复制到两个从 redis 服务上。 只有一个主 redis,可以有多个从 redis。 主从复制不会阻塞 master,在同步数据时,master 可以继续处理 client 请求。 一个 redis 可以即是主又是从,如下图:


主从配置
1、主 redis 配置
无需特殊配置。
2、从redis配置
修改从 redis 服务器上的 redis.conf 文件,添加 slaveof 主 redisip 主 redis 端口。

上边的配置说明当前该从 redis 服务器所对应的主 redis 是192.168.101.3,端口是6379。

主从复制过程
1、完整复制过程
在 redis2.8 版本之前主从复制过程如下图:

复制过程说明: slave 服务启动,slave 会建立和 master 的连接,发送 sync 命令。 master 启动一个后台进程将数据库快照保存到 RDB 文件中 注意:此时如果生成 RDB 文件过程中存在写数据操作会导致 RDB 文件和当前主 redis 数据不一致,所以此时 master 主进程会开始收集写命令并缓存起来。 master 就发送 RDB 文件给 slave slave 将文件保存到磁盘上,然后加载到内存恢复 master 把缓存的命令转发给 slave 注意:后续 master 收到的写命令都会通过开始建立的连接发送给 slave。
当 master 和 slave 的连接断开时 slave 可以自动重新建立连接。如果 master 同时收到多个 slave 发来的同步连接命令,只会启动一个进程来写数据库镜像,然后发送给所有 slave。
完整复制的问题: 在 redis2.8 之前从 redis 每次同步都会从主 redis 中复制全部的数据,如果从 redis 是新创建的从主 redis 中复制全部的数据这是没有问题的,但是,如果当从 redis 停止运行,再启动时可能只有少部分数据和主 redis 不同步,此时启动 redis 仍然会从主 redis 复制全部数据,这样的性能肯定没有只复制那一小部分不同步的数据高。
2、部分复制

部分复制说明: 从机连接主机后,会主动发起 PSYNC 命令,从机会提供 master 的 runid(机器标识,随机生成的一个串) 和 offset(数据偏移量,如果offset主从不一致则说明数据不同步),主机验证 runid 和 offset 是否有效,runid 相当于主机身份验证码,用来验证从机上一次连接的主机,如果 runid 验证未通过则,则进行全同步,如果验证通过则说明曾经同步过,根据 offset 同步部分数据。
数据库
2019-05-26 10:50:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
系统
# uname -a # 查看内核/操作系统/CPU信息
# lsb_release -a # 查看操作系统版本 (适用于所有的linux,包括Redhat、SuSE、Debian等发行版,但是在debian下要安装lsb)
# cat /proc/cpuinfo # 查看CPU信息
# hostname # 查看计算机名
# lspci -tv # 列出所有PCI设备
# lsusb -tv # 列出所有USB设备
# lsmod # 列出加载的内核模块
# env # 查看环境变量
资源
# free -m # 查看内存使用量和交换区使用量
# df -h # 查看各分区使用情况
# du -sh <目录名> # 查看指定目录的大小
# grep MemTotal /proc/meminfo # 查看内存总量
# grep MemFree /proc/meminfo # 查看空闲内存量
# uptime # 查看系统运行时间、用户数、负载
# cat /proc/loadavg # 查看系统负载
磁盘和分区
# mount | column -t # 查看挂接的分区状态
# fdisk -l # 查看所有分区
# swapon -s # 查看所有交换分区
# hdparm -i /dev/hda # 查看磁盘参数(仅适用于IDE设备)
# dmesg | grep IDE # 查看启动时IDE设备检测状况
网络
# ifconfig # 查看所有网络接口的属性
# iptables -L # 查看防火墙设置
# route -n # 查看路由表
# netstat -lntp # 查看所有监听端口
# netstat -antp # 查看所有已经建立的连接
# netstat -s # 查看网络统计信息
进程
# ps -ef # 查看所有进程
# top # 实时显示进程状态
用户
# w # 查看活动用户
# id <用户名> # 查看指定用户信息
# last # 查看用户登录日志
# cut -d: -f1 /etc/passwd # 查看系统所有用户
# cut -d: -f1 /etc/group # 查看系统所有组
# crontab -l # 查看当前用户的计划任务
服务
# chkconfig --list # 列出所有系统服务
# chkconfig --list | grep on # 列出所有启动的系统服务
程序
# rpm -qa # 查看所有安装的软件包

查看CPU信息(型号)
# cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
8 Intel(R) Xeon(R) CPU E5410 @ 2.33GHz
(看到有8个逻辑CPU, 也知道了CPU型号)
# cat /proc/cpuinfo | grep physical | uniq -c
4 physical id : 0
4 physical id : 1
(说明实际上是两颗4核的CPU)
# getconf LONG_BIT
32
(说明当前CPU运行在32bit模式下, 但不代表CPU不支持64bit)
# cat /proc/cpuinfo | grep flags | grep ' lm ' | wc -l
8
(结果大于0, 说明支持64bit计算. lm指long mode, 支持lm则是64bit)
再完整看cpu详细信息, 不过大部分我们都不关心而已.
# dmidecode | grep 'Processor Information'
其他
查看内存信息
# cat /proc/meminfo
# uname -a
Linux euis1 2.6.9-55.ELsmp #1 SMP Fri Apr 20 17:03:35 EDT 2007 i686 i686 i386 GNU/Linux
(查看当前操作系统内核信息)
# cat /etc/issue | grep Linux
Red Hat Enterprise Linux AS release 4 (Nahant Update 5)
(查看当前操作系统发行版信息)
查看机器型号
# dmidecode | grep "Product Name"
查看网卡信息
# dmesg | grep -i eth
数据库
2019-05-26 10:49:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
对查询进行优化,要尽量避免全表扫描,首先应考虑在进行条件判断的字段上创建了索引。
应尽量避免在where子句中对字段进行null值判断,使用!= 或 <>操作符等,否则将导致引擎放弃使用索引而进行全表扫描。
也不能在where子句中使用or来连接条件(应该用union all来使用两个语句),如果一个字段有索引另外一个字段没有索引也会导致引擎放弃使用索引而进行全表扫描。
not in应该慎用 , 用not exists代替not in
(mysql中)模糊查询避免使用“%”
避免在where子句中进行表达式计算操作
在使用索引字段作为条件是,如果该索引是复合索引那么必须使用到该索引中第一个字段作为条件时才能保证系统使用了索引(最左原则) ,否则该索引将不会被使用,并且应该尽可能的让字段顺序和索引顺序一致。所谓复合索引就是创建一个索引的时候作用在多个字段上。
updata语句,如果只更改一两个字段,不要update全部字段,否则频繁调用会引起明显的性能消耗,同时带来大量日志。
对于多张大数据量(这里几百条算大了)的表连接,可以考虑使用程序去实现,不要做连接查询,就是尽量避开多表查询。
索引并不是越多越好,索引固然可以提高相应的select的效率,但同时也降低了insert及update的效率,因为insert或update时有可能会重建索引,索引怎么样建索引需要慎重考虑,视具体情况而定。
尽量使用数字型字段,若只会数值信息的字段尽量不要设置为字符型,这回降低插叙和连接的性能,并会增加存储开销,这是因为引擎在处理查询和连接是会逐个比较字符串中每一个字符,而对于数据型而言只需要比较一次就够了。
任何地方都不要使用select*from,用具体的字段代替“*”,不要返回用不到的任何字段。
学会使用慢查询来进行数据库的优化。
数据库
2019-05-25 21:45:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
下载地址:https://dev.mysql.com/downloads/mysql/
安装步骤
1.下载zip解压到目录下
2.配置环境变量
新建系统变量:MYSQL_HOME,值:D:\DevelopmentTool\Mysql-5.7.26-winx64
修改path变量:%MYSQL_HOME%\bin;(在末端添加)
3.创建配置文件
在程序目录下创建my.ini配置文件(此处为:D:\DevelopmentTool\Mysql-5.7.26-winx64),文件内容如下: [mysqld] #绑定IPv4 bind-address = 0.0.0.0 # 设置mysql的安装目录,即你解压缩安装包的位置 basedir = D:/DevelopmentTool/Mysql-5.7.26-winx64 # 设置mysql数据库的数据的存放目录 datadir = D:/DevelopmentTool/Mysql-5.7.26-winx64/data # 设置端口号 port = 3306 # 允许最大连接数 max_connections = 200 # 设置字符集为utf8 loose-default-character-set = utf8 # 开启查询缓存 explicit_defaults_for_timestamp = true # windows下区分表名大小写(0:不区分,2区分(5.7版本)) lower_case_table_names=2 sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES [client] #设置客户端字符集 port=3306 default-character-set = utf8 [WinMySQLadmin] Server = D:/DevelopmentTool/Mysql-5.7.26-winx64/bin/mysqld.exe
4.注册windows系统服务 打开cmd(附件-命令提示符,右键超级管理员打开),否则可能会提示(Install/Remove of the Service Denied) 运行安装命令 mysqld install MySQL --defaults-file="%MYSQL_HOME%\my.ini" 备注:如果想要移除该服务,使用命令:mysqld -remove
5.启动服务
注意:此时是无法正常启动mysql服务的,因为5.7.18版本是不附带data文件夹的,需要通过命令来创建data文件夹和默认的数据库(如果存在,删除data目录下所有文件),然后执行创建命令:mysqld --initialize-insecure --user=mysql
启动服务方式1,执行命令:net start mysql 启动服务方式2,运行-services.msc,找到mysql服务,右键启动
6.修改root密码
刚完成安装时,密码是空的,我们可以通过命令行修改root账号的密码为root,保持一致。 打开cmd:mysql -uroot -p(提示 Enter password,直接回车,默认密码为空) use mysql; update user set authentication_string=password('root') WHERE user='root'; flush privileges; exit
7.常用命令
在命令行中,配置好环境变量后,通过cmd可以直接进入mysql命令行模式,同时列举几种常用命令 # 进入mysql数据库,密码可以先不写,打完-p后再输入,防止被别人看到 mysql -u账号 -p密码 -u 用户名 -p 密码 -h 服务器名称 -p 端口号 -D 打开指定数据库 --prompt=name 设置命令提示符 --delimiter=name 指定分隔符 -V,--version 输出版本信息并且退出 exit,quit,\q 退出 # 创建数据库 CREATE {DATABASE|SCHEMAS} [IF NOT EXISTS] db_name DEFAULT CHARACTER SET = 'UTF8|GBK|...'; CREATE DATABASE IF NOT EXISTS myWebSite; # 修改数据库编码方式 ALTER {DATABSE|SCHEMAS} db_name [DEFAULT] CHARACTER SET [=] charset_name; ALTER DATABSE myWebSiteDEFAULT CHARACTER SET = utf8; # 数据库列表 SHOW DATABASE; SHOW SCHEMAS; # 查看指定数据库定义 SHOW CREATE {DATABASE|CEHMAS} db_name; SHOW CREATE DATABASE myWebSite; # 查看上条数据库警告 SHOW WARNINGS; # 打开指定数据库和查看当前打开的数据库(如果忘记了) USE db_name; SELECT DATABASE()|SCHEMAS(); # 删除指定数据库 DROP {DATABASE|CEHMAS} [IF EXISTS] db_name; DROP DATABASE IF EXISTS myWebSite; # 查看数据表结构 DESC db_name; DESCRIBE db_name; SHOW COLUMNS FROM db_name; # UNSIGNED 无符号,移除负数范围,即无法填充负数范围的数值 CREATE TABLE table_name(num1 INT UNSIGNED); # ZEROFILL 自动补充0,创建数据表时,会根据其位数自动在前面补0,如int,默认十位数范围,填充1数字,会变成0000000001 CREATE TABLE table_name(num1 INT ZEROFILL);
8.配置mysql输出日志到指定位置
在sql命令行中,输入以下命令即可 \T D:\SQLlog\syslog.txt
9.数据类型(需要注意的)
字符串-枚举类型 ENUM ENUM(temp1,temp2,temp3) 注意:设置的字符串中含有空格将自动忽略 栗子:CREATE TABLE IF NOT EXISTS test(sex ENUM('男','女','保密')); 测试:INSERT test VALUES('男'); 错误:存入的值与枚举中地值不一致时会报错 测试:INSERT test VALUES('男1'); 特殊1:存入的值可以为序号,序号值从1开始,即男为1,女为2,保密为3 测试1:INSERT test VALUES(1); 特殊2:如果设置的字段可以为NUll,则也可以键入 测试2:INSERT test VALUES(NULL);
字符串-集合类型 SET SET(temp1,temp2,temp3) 注意:设置的字符串中含有空格将自动忽略 栗子:CREATE TABLE IF NOT EXISTS test(favour SET('A','B','C','D')); 测试:INSERT test VALUES('A,C,D');INSERT test VALUES('D,B,A'); 特殊1:存入的值是以2进制来保存,可以使用2进制来控制值,ABCD分别以1、2、4、8来表示,这里键入3,则表示保存AB,15则表示保存所有 测试1:INSERT test VALUES(3);INSERT test VALUES(15);
注:另外一篇文章来继续后面的内容。


数据库
2019-05-25 17:29:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
先简单解释一下笛卡尔积。
现在,我们有两个集合A和B。
A = {0,1} B = {2,3,4}
集合 A×B 和 B×A的结果集就可以分别表示为以下这种形式:
A×B = {(0,2),(1,2),(0,3),(1,3),(0,4),(1,4)};
B×A = {(2,0),(2,1),(3,0),(3,1),(4,0),(4,1)};
以上A×B和B×A的结果就可以叫做两个集合相乘的‘笛卡尔积’。
从以上的数据分析我们可以得出以下两点结论:
1,两个集合相乘,不满足交换率,既 A×B ≠ B×A;
2,A集合和B集合相乘,包含了集合A中元素和集合B中元素相结合的所有的可能性。既两个集合相乘得到的新集合的元素个数是 A集合的元素个数 × B集合的元素个数;
MySQL的多表查询(笛卡尔积原理) 先确定数据要用到哪些表。 将多个表先通过笛卡尔积变成一个表。 然后去除不符合逻辑的数据(根据两个表的关系去掉)。 最后当做是一个虚拟表一样来加上条件即可。
数据库表连接数据行匹配时所遵循的算法就是以上提到的笛卡尔积,表与表之间的连接可以看成是在做乘法运算。
比如现在数据库中有两张表,student表和 student_subject表,如下所示:
  
我们执行以下的sql语句,只是纯粹的进行表连接。 SELECT * from student JOIN student_subject; SELECT * from student_subject JOIN student;
看一下执行结果:
  
  表1.0                            表1.1
从执行结果上来看,结果符合我们以上提出的两点结论(红线标注部分);
以第一条sql语句为例我们来看一下他的执行流程,
1,from语句把student表 和 student_subject表从数据库文件加载到内存中。
2,join语句相当于对两张表做了乘法运算,把student表中的每一行记录按照顺序和student_subject表中记录依次匹配。
3,匹配完成后,我们得到了一张有 (student中记录数 × student_subject表中记录数)条的临时表。 在内存中形成的临时表如表1.0所示。我们又把内存中表1.0所示的表称为‘笛卡尔积表’。

  针对以上的理论,我们提出一个问题,难道表连接的时候都要先形成一张笛卡尔积表吗,如果两张表的数据量都比较大的话,那样就会占用很大的内存空间这显然是不合理的。所以, 我们在进行表连接查询的时候一般都会使用JOIN xxx ON xxx的语法,ON语句的执行是在JOIN语句之前的,也就是说两张表数据行之间进行匹配的时候,会先判断数据行是否符合ON语句后面的条件,再决定是否JOIN 。
  因此,有一个显而易见的SQL优化的方案是,当两张表的数据量比较大,又需要连接查询时,应该使用 FROM table1 JOIN table2 ON xxx的语法,避免使用 FROM table1,table2 WHERE xxx 的语法,因为后者会在内存中先生成一张数据量比较大的笛卡尔积表,增加了内存的开销。
下面引出Mysql的左右连接和内连接的笛卡尔积...
 一个同事跟我讨论左连接查询,是不是笛卡尔积。我第一反应,左连接肯定不是笛卡尔积啊,左连接是以左表为准,左表有m条记录,则结果集是m条记录(哈哈,如果是你,你是不是也是这样的反映),同事听了,说内连接会是笛卡尔积。在数据库里试验了一下,发现,事实比想象中要复杂。
首先说下结论:链接查询,如果on条件是非唯一字段,会出现笛卡尔积(局部笛卡尔积);如果on条件是表的唯一字段,则不会出现笛卡尔积。
  下面是具体的试验:( 以真三国无双v3.9d蜀国阵容为例... )
  文中会有两张表,user表和job表,表数据如下,其中user为5条记录,job为4条记录
USER: job:

1.交叉连接
如果A表有m(5)条记录,m1条符合on条件,B表有n(4)条记录,有n1条符合on条件,无条件交叉连接的结果为: m*n=5*4=20 SELECT * FROM `user` CROSS JOIN job;
这种等同于(交叉查询等于不加on的内连接) SELECT * FROM `user` , job;
sql执行结果:总共20条记录
   结论:交叉连接,会产生笛卡尔积。
2.内连接(可以当做左连接的特殊情况,只保留符合主表中on条件的记录)
(1)内连接唯一字段
如果A表有m(5)条记录,m1(4)条符合on条件,B表有n(4)条记录,有n1(3)条符合on条件,内连接唯一字段结果为:Max(m1,n1)=4
1,2,2,6,7 和 1,2,7,8对比,以user表为主表,因为主表中有4条符合条件的记录(1,2,2,7),而job表有3条符合条件的记录(1,2,7),取两者中的最大的,所以为4条 SELECT * FROM `user` u JOIN job j ON u.JOB_ID=j.ID;
sql执行结果为:4条记录
   结论:假如,内连接查询,on条件是A表或者B表的唯一字段,则结果集是两表的交集,不是笛卡尔积。

(2)内连接非唯一字段
如果A表有m(5)条记录,m1(2)条符合on条件,B表有n(4)条记录,有n1(3)条符合on条件,则结果集是Max(m1,n1)=3条
1,2,2,6,7 和 1,1,7,8对比,以user表为主表,因为主表中有2条符合条件的记录(1,7),而job表有3条符合条件的记录(1,1,7),取两者中的最大的,所以为 3 条 SELECT * FROM `user` u JOIN job j ON u.valid=j.valid;
   结论:假如,on条件是表中非唯一字段,则结果集是两表匹配到的结果集的笛卡尔积(局部笛卡尔积) 。
3.外连接
(1)左连接
a.左连接唯一字段
假如A表有m(5)条记录,B表有n(4)条记录,则结果集是m=5
1,2,2,6,7 和 1,2,7,8对比,以user表为主表,因为主表中有4条符合条件的记录(1,2,2,7),而job表有3条符合条件的记录(1,2,7),取两者中的最大的,所以取 4 条,然后再加上user表中没有在job表中找到对应关系的记录(即对应的job表都为null,5-4= 1 ),所以最终结果为 4+1=5 条 SELECT * FROM USER u LEFT JOIN job j ON u.JOB_ID=j.id;
SQL查询结果:5条记录
结论:on条件是唯一字段,则结果集是左表记录的数量。
b.左连接非唯一字段
1,2,2,6,7 和 1,1,7,8对比,以user表为主表,因为主表中有2条符合条件的记录(1,7),而job表有3条符合条件的记录(1,1,7),取两者中的最大的,所以取 3 条,然后在加上user表在job表中没有匹配的记录(即对应的job表都为null,为5-2= 3 ),所以最终结果为 3+3=6 条 SELECT * FROM `user` u LEFT JOIN job j ON u.VALID=j.VALID;
   结论:左连接非唯一字段,是局部笛卡尔积。

c.当on 条件为假时的内连接: SELECT * FROM `user` u LEFT JOIN job j ON 0;
sql查询结果:5条
结论:当on条件为假的时候,即user在job表中一条符合记录的都没有,那么即为:user表中的所有记录条数,所以为5条,job表中的值都为null
(2)右连接
  同左连接,这里就不赘述了
全外连接
  mysql不支持
总结:左右连接是否产生笛卡尔积,和on的条件是否为唯一索引没有关系,只和左表、右表两者各自匹配on条件的记录条数有关系( 左连接和右连接可以这么做:1:由INNER JOIN查询全匹配记录;2:查询左表或者右表没有符合on条件的记录;3.全匹配记录+没有匹配上的记录就是左连接或者右连接查询的结果集 )
1.全匹配:
无论哪种查询,首先计算出on匹配记录(FROM user INNER JOIN job ON ...或者使用 FROM user,job where...),匹配记录的查询结果为:若A表有m条记录,符合on查询条件的为m1条,B表有n条记录,符合on条件的为n1条,那么匹配记录为MAX(m1,n1);
2.左连接:
结果集为: MAX(m1,n1)+(m-m1);
如果m1 > n1,则不会产生笛卡尔积,因为无论不匹配的记录(m-m1),还是匹配的记录MAX(m1,n1),都是从左表中取记录,所以不会出现重复的记录;反之,如果m1 < n1,则一定会产生笛卡尔积,因为MAX(m1,n1)是从右表中取的,而根据笛卡尔积的原理,右表中的每条记录都会和左表中的所有记录匹配一次,所以符合on条件的n1条记录也一定会和左表中的所有记录都匹配一次,而左表中符合记录只有m1条,所以造成笛卡尔积的条数为(n1-m1)条
即用内连接的记录(MAX(m1,n1)),加上左表没有满足on条件的记录(m-m1 ),所以为:MAX(m1,n1)+(m-m1);
3.有连接
结果集为:MAX(m1,n1)+(n-n1);
如果m1 < n1,则不会产生笛卡尔积,因为无论不匹配的记录(n-n1),还是匹配的记录MAX(m1,n1),都是从右表中取记录,所以不会出现重复的记录;反之,如果m1 > n1,则一定会产生笛卡尔积,因为MAX(m1,n1)是从左表中取的,所以造成笛卡尔积的记录条数为(m1-n1)条
即用内连接的记录(MAX(m1,n1)),加上右表没有满足on条件的记录(n-n1 ),所以为:MAX(m1,n1)+(n-n1) ;
下面再来谈下:
Mysql:ON 与 WHERE 的区别
很多同学在学习 Mysql 表关联的时候弄不清 ON 与 WHERE 的区别,不知道条件应该写在 ON 里面还是 WHERE 里面,作者在工作的时候也入过坑,总觉得条件写在哪里查询结果都是一样的,最后出错坏了事,差点惹了大祸。所以今天简单易懂的总结一下他们的区别,大家共同学习。
准备工作
我们先准备两个表,并造一些数据:
表t1: CREATE TABLE `t1` ( `id` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '主键id', `name` CHAR(100) NOT NULL DEFAULT '' COMMENT '姓名', `age` INT(11) NOT NULL DEFAULT '0' ) ENGINE=INNODB DEFAULT CHARSET=utf8; INSERT INTO `t1`(`id`,`name`,`age`) VALUES (1,'C罗',33),(2,'梅西',31),(3,'内马尔',29);
表t2: CREATE TABLE `t2` ( `id` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '主键id', `goals` INT(11) NOT NULL DEFAULT '0' COMMENT '进球数', `matches` INT(11) NOT NULL DEFAULT '0' COMMENT '比赛编号' ) ENGINE=INNODB DEFAULT CHARSET=utf8; INSERT INTO `t2`(`id`,`goals`,`matches`) VALUES (1,3,1),(1,5,2),(2,0,1),(2,8,2);
查询结果如图:
表t1记录:
表t2记录:
探究
口诀:先执行 ON ,后执行 WHERE ; ON 是建立关联关系, WHERE 是对关联关系的筛选 。
记住这句话就可以准确地判断查询结果了,我们通过两个 sql 来进行分析:
SQL1 : SELECT t1.id,t2.id,t1.name,t1.age,t2.`matches` FROM t1 LEFT JOIN t2 ON t1.id = t2.id WHERE matches = 2; -- 条件放在 WHERE
前提是 LEFT JOIN ,所以左边的数据在创建关联关系时会保留,根据口诀,先执行 ON 建立关联关系,形成子表,最后在子表中通过 WHERE 筛选,过程如下:
左表符合记录的t1.id = t2.id的记录有2条,右表符合记录的有4条,所以MAX(m1,n1)为4条,其中左表没有符合on条件的记录为(3-2=1)条,所以LEFT JOIN的结果总共有5条,最后一条左表没有匹配上右表记录,所以右表的属性都为null,如下:
但是最终结果从5条记录中再通过where进行筛选,即matches为2,所以结果只有2条( 注意先LEFT JOIN,然后再是where,所以此时5条记录中不符合where条件的记录会被排除,即最终的结果不再是左表所有的记录 ):

SQL2: SELECT t1.id,t2.id,t1.name,t1.age,t2.`matches` FROM t1 LEFT JOIN t2 ON t1.id = t2.id AND matches = 2; -- 条件放在 ON
SQL2没有 WHERE ,那么 ON 建立的关联关系就是最终结果(因为没有where条件进行最终筛选,所有最终结果为内联记录加上左表中没有符合on条件的记录):
符合ON条件的记录,改为内联INNER JOIN ,查询基础数据: MAX(m1,n1) SELECT t1.id,t2.id,t1.name,t1.age,t2.`matches` FROM t1 INNER JOIN t2 ON t1.id = t2.id AND matches = 2;
所以 MAX(m1,n1)为2条, 结果为:
再由基础数据加上左表没有匹配上的记录数(只有id为3的没有匹配上,即 (n-n1) = 1 )只有1条,所以最终结果为:
最终结果为: MAX(m1,n1)+(m-m1) = 2 + (id为3的记录) = 3条
通过这两个 sql 可以很好的区分 WHERE 和 ON 的区别了,希望大家使用的时候多注意这一点,避免犯错!
逻辑上一个query的执行顺序(不是实际)
1. FROM
2. ON
3. JOIN
4. WHERE
5. GROUP BY
6. WITH CUBE or WITH ROLLUP
7. HAVING
8. SELECT
9. DISTINCT
10. ORDER BY
11. TOP
说是“逻辑上” 顺序,因为实际执行时还要看索引,数据分布等,看最终优化器如何处理,最真实的顺序肯定是执行计划展示的顺序。
QL语句中join连表时on和where后都可以跟条件,那么对查询结果集,执行顺序,效率是如何呢?
通过查询资料发现:
区别:
on是对中间结果进行筛选,where是对最终结果筛选。
执行顺序:
先进行on的过滤, 而后才进行join。
效率:
如果是inner join, 放on和放where产生的结果一样, 但没说哪个效率速度更高? 如果有outer join (left or right), 就有区别了, 因为on生效在先, 已经提前过滤了一部分数据, 而where生效在后.
最后来了解下T-SQL对查询逻辑处理。
T-SQL逻辑查询的各个阶段( 编号代表顺序 ):
(5)SELECT DISTINCT TOP()
(1)FROM JOIN ON
(2)WHERE
(3)GROUP BY
(4)HAVING
(6)ORDER BY
T-SQL在查询各个阶级分别干了什么:
(1)FROM 阶段
FROM阶段标识出查询的来源表,并处理表运算符。在涉及到联接运算的查询中(各种join),主要有以下几个步骤:
   a.求笛卡尔积 。 不论是什么类型的联接运算,首先都是执行交叉连接 (cross join),求笛卡儿积,生成虚拟表VT1-J1。
b.ON筛选器 。这个阶段对上个步骤生成的VT1-J1进行筛选,根据ON子句中出现的谓词进行筛选,让谓词取值为true的行通过了考验,插入到VT1-J2。
c.添加外部行 。如果指定了outer join,还需要将VT1-J2中没有找到匹配的行,作为外部行添加到VT1-J2中,生成VT1-J3。
经过以上步骤,FROM阶段就完成了。概括地讲,FROM阶段就是进行预处理的,根据提供的运算符对语句中提到的各个表进行处理(除了join,还有apply,pivot,unpivot)
(2)WHERE阶段
WHERE阶段是根据中条件对VT1中的行进行筛选,让条件成立的行才会插入到VT2中。
(3)GROUP BY阶段
GROUP阶段按照指定的列名列表,将VT2中的行进行分组,生成VT3。最后每个分组只有一行。
(4)HAVING阶段
该阶段根据HAVING子句中出现的谓词对VT3的分组进行筛选,并将符合条件的组插入到VT4中。
(5)SELECT阶段
  这个阶段是投影的过程,处理SELECT子句提到的元素,产生VT5。这个步骤一般按下列顺序进行
a.计算SELECT列表中的表达式,生成VT5-1。
b.若有DISTINCT,则删除VT5-1中的重复行,生成VT5-2
c.若有TOP,则根据ORDER BY子句定义的逻辑顺序,从VT5-2中选择签名指定数量或者百分比的行,生成VT5-3
(6)ORDER BY阶段
根据ORDER BY子句中指定的列明列表,对VT5-3中的行,进行排序,生成游标VC6.
如果是inner join, 放on和放where产生的结果一样, 执行计划也是一样, 但推荐使用on 。但如果有outer join (left or right), 就有区别了, 因为on生效在先, 已经提前过滤了一部分数据, 而where生效在后,而且where对于outer join有不生效的情况
使用left join时on后面的条件只对右表有效 on是在生成临时表的时候使用的条件,不管on的条件是否起到作用,都会返回左表 (table_name1) 的行。 where则是在生成临时表之后使用的条件,此时已经不管是否使用了left join了,只要条件不为真的行,全部过滤掉。
数据库
2019-05-25 10:50:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
在8版本以后的MySql默认的加密方式都改为了caching_sha2_password
因此进入mysql的命令行更改加密方式即可
ALTER USER 'root'@'localhost' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER; #更改加密方式

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码'; #更新用户密码

FLUSH PRIVILEGES; #刷新权限
数据库
2019-05-21 16:35:01
「深度学习福利」大神带你进阶工程师,立即查看>>>
5月21日,阿里云PolarDB发布重大更新,提供传统数据库一键迁移上云能力,可以帮助企业将线下的MySQL、PostgreSQL和Oracle等数据库轻松上云,最快数小时内迁移完成。据估算,云上成本不到传统数据库的1/6。目前,已有约40万个数据库迁移到阿里云上。
阿里云方面表示,该产品实现了两大技术突破:通过自研超低延迟文件系统PolarFS大幅降低数据跨网络的延迟,并且开发了一种全新的共识协议ParallelRaft,提升系统吞吐量。在此之前,PolarFS的研究成果已发表在数据库顶级会议 VLDB 2018 《PolarFS: An Ultra-low Latency and Failure Resilient Distributed File System for Shared Storage Cloud Database》。

企业在使用传统商业数据库时,经常会面临授权费用贵、硬件成本高、架构与运维复杂、迁移难度大等问题,此次云原生数据库PolarDB的重大更新针对此类痛点,实现一键快速迁移,并提供云上的完整生态服务。
此外,产品还具备三大亮点,满足企业在数字时代海量的数据存储需求:1、单实例规格最大达88核710GB;2、业内最快单节点读写速度100万QPS;3、实现三份数据存储实时同步0延迟。除性能领先外,云上数据库成本也低于传统数据库,不到后者的1/6。
PolarDB是阿里云在2018年正式商业化的云原生数据库,采用存储计算分离、软硬一体化设计,具备快速弹性能力、超大规格、超高可靠性以及两倍于AWS Aurora的性能。目前已是阿里云上增长最快的数据库产品。
随着移动互联网、物联网的发展,数据量剧增。企业上云也成大势所趋,企业上云意愿达84%,云也对数据库提出了更高的扩展性和可用性要求。
因昂贵、扩展性差、技术复杂、迭代慢,传统商业数据库饱受诟病。与传统数据库相反,云原生数据库天然拥有云计算的弹性能力,兼具开源数据库的易用、开放特点,及传统数据库的管理和处理性能优势,是云时代下企业数据库的最佳选择。
在全球范围内,一场替换传统数据库的行动正在进行。早在2013年,阿里巴巴就将最后一台Oracle数据库从其淘宝核心系统中下线。亚马逊也公开表示,将在2020年彻底放弃Oracle数据库。
阿里云智能数据库事业部负责人李飞飞表示,云原生数据库在成本、灵活度、安全、技术进化层面都优于传统数据库,传统数据库会像马车一样被淘汰。
阿里云拥有国内最丰富的云数据库产品,目前已有约40万个数据库迁移到阿里云上,涵盖金融、电信、制造、物流等领域的龙头企业。在Gartner发布的2018年数据库魔力象限中,阿里云是国内首个进入挑战者象限的中国公司。
阿里云数据库的技术研究也在国际上崭露头角。PolarDB相关论文入选今年的国际顶级数据库会议SIGMOD,这是阿里云数据库连续第二年入选该学术会议。
作者:阿里云头条
原文链接 ​
本文为云栖社区原创内容,未经允许不得转载。
数据库
2019-05-21 16:32:08
「深度学习福利」大神带你进阶工程师,立即查看>>>
问题现象:
报警文件中一直在报下面的错误:
Thu Jul 26 23:04:42 2012
Errors in file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_j000_31365.trc:
ORA-12012: 自动执行作业 23 出错
ORA-12005: 不能安排过去时间的自动刷新
Thu Jul 26 23:06:42 2012
Errors in file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_j000_31383.trc:
ORA-12012: 自动执行作业 23 出错
ORA-12005: 不能安排过去时间的自动刷新
Thu Jul 26 23:10:43 2012
Errors in file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_j000_31417.trc:
ORA-12012: 自动执行作业 23 出错
ORA-12005: 不能安排过去时间的自动刷新
Thu Jul 26 23:18:43 2012
Errors in file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_j000_31478.trc:
ORA-12012: 自动执行作业 23 出错
ORA-12005: 不能安排过去时间的自动刷新
Thu Jul 26 23:34:44 2012
Errors in file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_j000_31614.trc:
ORA-12012: 自动执行作业 23 出错
ORA-12005: 不能安排过去时间的自动刷新
问题解决:
该问题应该是job执行后,计算job的下一个执行时间时,发现比当前的时间还早,就报这个错误:
检查23号job
select job,last_date,next_date,interval from dba_jobs;
23 2012-7-28 0:06:47 00:06:47 2012-7-28 23:04:37 23:04:37 (trunc(sysdate)+25/26)
主要为这个间隔时间为 (trunc(sysdate)+25/26)
select (trunc(sysdate)+25/26) from dual;
这个时间为当天的 23:04:37 ,所以无法执行
修改为'trunc(sysdate)+25/24'即可.
具体修改过程为:
Execute DBMS_JOB.INTERVAL (23, 'trunc(sysdate)+25/24');
数据库
2019-05-21 16:05:00
「深度学习福利」大神带你进阶工程师,立即查看>>> Option Explicit ValidationMode = True InteractiveMode = im_Batch Dim mdl ' the current model ' get the current active model Set mdl = ActiveModel If (mdl Is Nothing) Then MsgBox "There is no current Model " ElseIf Not mdl.IsKindOf(PdPDM.cls_Model) Then MsgBox "The current model is not an Physical Data model. " Else ProcessFolder mdl End If ' This routine copy name into comment for each table, each column and each view ' of the current folder Private sub ProcessFolder(folder) Dim Tab 'running table for each Tab in folder.tables if not tab.isShortcut then tab.comment = tab.name Dim col ' running column for each col in tab.columns col.comment= col.name next end if next Dim view 'running view for each view in folder.Views if not view.isShortcut then view.comment = view.name end if next ' go into the sub-packages Dim f ' running folder For Each f In folder.Packages if not f.IsShortcut then ProcessFolder f end if Next end sub
数据库
2019-05-21 14:38:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
mysql [Err] 1118 - Row size too large (> 8126).
问题
mysql5.7 在执行创建表或者增加字段时,发现row size长度过长,导致出现以下错误。 [Err] 1118 - Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
解决方案
row size 其实就是所有字段的长度的总和。 在不进行拆表的前提下解决(我们不讨论是否设计的合理性) : 知识贴: https://dev.mysql.com/doc/refman/8.0/en/column-count-limit.html You may want to take a look at this article which explains a lot about MySQL row sizes. It's important to note that even if you use TEXT or BLOB fields, your row size could still be over 8K (limit for InnoDB) because it stores the first 768 bytes for each field inline in the page. The simplest way to fix this is to use the Barracuda file format with InnoDB. This basically gets rid of the problem altogether by only storing the 20 byte pointer to the text data instead of storing the first 768 bytes.
方法一:改变一些字段varchar为TEXT or BLOB。 无效,不能解决问题。
最终解决方案
https://stackoverflow.com/questions/22637733/mysql-error-code-1118-row-size-too-large-8126-changing-some-columns-to-te
查询系统参数: show variables like '%innodb_strict_mode%'; show variables like '%innodb_log_file_size%';
修改前: innodb_strict_mode ON innodb_log_file_size 536870912
修改mysql的配置文件, vi /etc/my.cnf innodb_log_file_size=1024M innodb_strict_mode=0
innodb_strict_mode=0 这个一定不能漏,否则不能生效。 重启后: innodb_strict_mode OFF innodb_log_file_size 1073741824
it work 。 卡了很久,最终靠这个方案解决了。
数据库
2019-05-21 09:11:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Base Enviroment:CentOS release 6.5 +10.1.40-MariaDB MariaDB Server
安装完后,经过Navicat客户端工具,java web项目,linux操作系统myql客户端,三个维度(客户端)的实测。
实测结果是:此工程只能做到,命令行发起的对数据库的操作。
1.安装mysql-sniffer:
#yum install glib2-devel libpcap-devel libnet-devel
# cd /usr/local/src/
​#git clone https://github.com/Qihoo360/mysql-sniffer #此步较慢,耐心等待……
#cd mysql-sniffer
#mkdir proj
#cd proj
#cmake ../
#make
#cd bin/
2.参数查看
./mysql-sniffer -h Usage ./bin/mysql-sniffer [-d] -i eth0 -p 3306,3307,3308 -l /var/log/mysql-sniffer/ -e stderr [-d] -i eth0 -r 3000-4000 -d daemon mode. -s how often to split the log file(minute, eg. 1440). if less than 0, split log everyday -i interface. Default to eth0 -p port, default to 3306. Multiple ports should be splited by ','. eg. 3306,3307 this option has no effect when -f is set. -r port range, Don't use -r and -p at the same time -l query log DIRECTORY. Make sure that the directory is accessible. Default to stdout. -e error log FILENAME or 'stderr'. if set to /dev/null, runtime error will not be recorded -f filename. use pcap file instead capturing the network interface -w white list. dont capture the port. Multiple ports should be splited by ','. -t truncation length. truncate long query if it's longer than specified length. Less than 0 means no truncation -n keeping tcp stream count, if not set, default is 65536. if active tcp count is larger than the specified count, mysql-sniffer will remove the oldest one
3.执行命令,将mysql3306端口流量打到某网卡上(如 eth0 )
实时查看>>>>>
# ./bin/mysql-sniffer -i eth0 -p 3306
打到某日志文件>>
# ./bin/mysql-sniffer -i eth0 -p 3306 -l /tmp/mysql-sniffer/
查看网卡
4.查看效果:
mysql服务器启动mysql-sniffer开启实时监控
【方式一:windows电脑使用mysql客户端navicat访问mysql服务器的审计情况】

执行sql语句。
审计控制台并没有回显具体的执行语句,再次更改sql语句,控制台不会在有任何信息显示。
【方式二:java web项目访问数据库,控制台同样没有任何涉及信息】
【方式三:命令行终端】
可以看到完整的审计信息,从登陆数据库到登录后执行的具体sql(查询表,更新表等)审计控制台可以做到完全回显

【审计控制台终端情况如下:】

【源码地址:】
https://github.com/Qihoo360/mysql-sniffer/blob/master/README_CN.md
数据库
2019-05-24 12:07:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
即使你认为自己已对 MySQL 的 LEFT JOIN 理解深刻,但我敢打赌,这篇文章肯定能让你学会点东西! ON 子句与 WHERE 子句的不同 一种更好地理解带有 WHERE ... IS NULL 子句的复杂匹配条件的简单方法 Matching-Conditions 与 Where-conditions 的不同
关于 “A LEFT JOIN B ON 条件表达式” 的一点提醒
ON 条件( “A LEFT JOIN B ON 条件表达式” 中的 ON )用来决定如何从 B 表中检索数据行。
如果 B 表中没有任何一行数据匹配 ON 的条件,将会额外生成一行所有列为 NULL 的数据
在匹配阶段 WHERE 子句的条件都不会被使用。仅在匹配阶段完成以后, WHERE 子句条件才会被使用。它将从匹配阶段产生的数据中检索过滤。
让我们看一个 LFET JOIN 示例: mysql> CREATE TABLE `product` ( `id` int(10) unsigned NOT NULL auto_increment, `amount` int(10) unsigned default NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 mysql> CREATE TABLE `product_details` ( `id` int(10) unsigned NOT NULL, `weight` int(10) unsigned default NULL, `exist` int(10) unsigned default NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 mysql> INSERT INTO product (id,amount) VALUES (1,100),(2,200),(3,300),(4,400); Query OK, 4 rows affected (0.00 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> INSERT INTO product_details (id,weight,exist) VALUES (2,22,0),(4,44,1),(5,55,0),(6,66,1); Query OK, 4 rows affected (0.00 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM product; +----+--------+ | id | amount | +----+--------+ | 1 | 100 | | 2 | 200 | | 3 | 300 | | 4 | 400 | +----+--------+ 4 rows in set (0.00 sec) mysql> SELECT * FROM product_details; +----+--------+-------+ | id | weight | exist | +----+--------+-------+ | 2 | 22 | 0 | | 4 | 44 | 1 | | 5 | 55 | 0 | | 6 | 66 | 1 | +----+--------+-------+ 4 rows in set (0.00 sec) mysql> SELECT * FROM product LEFT JOIN product_details ON (product.id = product_details.id); +----+--------+------+--------+-------+ | id | amount | id | weight | exist | +----+--------+------+--------+-------+ | 1 | 100 | NULL | NULL | NULL | | 2 | 200 | 2 | 22 | 0 | | 3 | 300 | NULL | NULL | NULL | | 4 | 400 | 4 | 44 | 1 | +----+--------+------+--------+-------+ 4 rows in set (0.00 sec)
ON 子句和 WHERE 子句有什么不同?
一个问题 :下面两个查询的结果集有什么不同么? SELECT * FROM product LEFT JOIN product_details ON (product.id = product_details.id) AND product_details.id=2; SELECT * FROM product LEFT JOIN product_details ON (product.id = product_details.id) WHERE product_details.id=2;
用例子来理解最好不过了: mysql> SELECT * FROM product LEFT JOIN product_details ON (product.id = product_details.id) AND product_details.id=2; +----+--------+------+--------+-------+ | id | amount | id | weight | exist | +----+--------+------+--------+-------+ | 1 | 100 | NULL | NULL | NULL | | 2 | 200 | 2 | 22 | 0 | | 3 | 300 | NULL | NULL | NULL | | 4 | 400 | NULL | NULL | NULL | +----+--------+------+--------+-------+ 4 rows in set (0.00 sec) mysql> SELECT * FROM product LEFT JOIN product_details ON (product.id = product_details.id) WHERE product_details.id=2; +----+--------+----+--------+-------+ | id | amount | id | weight | exist | +----+--------+----+--------+-------+ | 2 | 200 | 2 | 22 | 0 | +----+--------+----+--------+-------+ 1 row in set (0.01 sec)
第一条查询使用 ON 条件决定了从 LEFT JOIN的 product_details表中检索符合的所有数据行。
第二条查询做了简单的LEFT JOIN,然后使用 WHERE 子句从 LEFT JOIN的数据中过滤掉不符合条件的数据行。
再来看一些示例: mysql> mysql> SELECT * FROM product LEFT JOIN product_details ON product.id = product_details.id AND product.amount=100; +----+--------+------+--------+-------+ | id | amount | id | weight | exist | +----+--------+------+--------+-------+ | 1 | 100 | NULL | NULL | NULL | | 2 | 200 | NULL | NULL | NULL | | 3 | 300 | NULL | NULL | NULL | | 4 | 400 | NULL | NULL | NULL | +----+--------+------+--------+-------+ 4 rows in set (0.00 sec)
所有来自product表的数据行都被检索到了,但没有在product_details表中匹配到记录(product.id = product_details.id AND product.amount=100 条件并没有匹配到任何数据) mysql> SELECT * FROM product LEFT JOIN product_details ON (product.id = product_details.id) AND product.amount=200; +----+--------+------+--------+-------+ | id | amount | id | weight | exist | +----+--------+------+--------+-------+ | 1 | 100 | NULL | NULL | NULL | | 2 | 200 | 2 | 22 | 0 | | 3 | 300 | NULL | NULL | NULL | | 4 | 400 | NULL | NULL | NULL | +----+--------+------+--------+-------+ 4 rows in set (0.01 sec)
同样,所有来自product表的数据行都被检索到了,有一条数据匹配到了。
使用 WHERE ... IS NULL 子句的 LEFT JOIN
当你使用 WHERE ... IS NULL 子句时会发生什么呢?
如前所述,WHERE 条件查询发生在 匹配阶段之后,这意味着 WHERE ... IS NULL 子句将从匹配阶段后的数据中过滤掉不满足匹配条件的数据行。
纸面上看起来很清楚,但是当你在 ON 子句中使用多个条件时就会感到困惑了。
我总结了一种简单的方式来理解上述情况: 将 IS NULL 作为否定匹配条件 使用 !(A and B) == !A OR !B 逻辑判断
看看下面的示例: mysql> SELECT a.* FROM product a LEFT JOIN product_details b ON a.id=b.id AND b.weight!=44 AND b.exist=0 WHERE b.id IS NULL; +----+--------+ | id | amount | +----+--------+ | 1 | 100 | | 3 | 300 | | 4 | 400 | +----+--------+ 3 rows in set (0.00 sec)
让我们检查一下 ON 匹配子句: (a.id=b.id) AND (b.weight!=44) AND (b.exist=0)
我们可以把 IS NULL 子句 看作是否定匹配条件。
这意味着我们将检索到以下行: !( exist(b.id that equals to a.id) AND b.weight !=44 AND b.exist=0 ) !exist(b.id that equals to a.id) || !(b.weight !=44) || !(b.exist=0) !exist(b.id that equals to a.id) || b.weight =44 || b.exist=1
就像在C语言中的逻辑 AND 和 逻辑 OR表达式一样,其操作数是从左到右求值的。如果第一个参数做够判断操作结果,那么第二个参数便不会被计算求值(短路效果)
看看别的示例: mysql> SELECT a.* FROM product a LEFT JOIN product_details b ON a.id=b.id AND b.weight!=44 AND b.exist=1 WHERE b.id IS NULL; +----+--------+ | id | amount | +----+--------+ | 1 | 100 | | 2 | 200 | | 3 | 300 | | 4 | 400 | +----+--------+ 4 rows in set (0.00 sec)
Matching-Conditions 与 Where-conditions 之战
如果你吧基本的查询条件放在 ON 子句中,把剩下的否定条件放在 WHERE 子句中,那么你会获得相同的结果。
例如,你可以不这样写: SELECT a.* FROM product a LEFT JOIN product_details b ON a.id=b.id AND b.weight!=44 AND b.exist=0 WHERE b.id IS NULL;
你可以这样写: SELECT a.* FROM product a LEFT JOIN product_details b ON a.id=b.id WHERE b.id is null OR b.weight=44 OR b.exist=1;
mysql> SELECT a.* FROM product a LEFT JOIN product_details b ON a.id=b.id WHERE b.id is null OR b.weight=44 OR b.exist=1; +----+--------+ | id | amount | +----+--------+ | 1 | 100 | | 3 | 300 | | 4 | 400 | +----+--------+ 3 rows in set (0.00 sec)
你可以不这样写: SELECT a.* FROM product a LEFT JOIN product_details b ON a.id=b.id AND b.weight!=44 AND b.exist!=0 WHERE b.id IS NULL;
可以这样写: SELECT a.* FROM product a LEFT JOIN product_details b ON a.id=b.id WHERE b.id is null OR b.weight=44 OR b.exist=0;
mysql> SELECT a.* FROM product a LEFT JOIN product_details b ON a.id=b.id WHERE b.id is null OR b.weight=44 OR b.exist=0; +----+--------+ | id | amount | +----+--------+ | 1 | 100 | | 2 | 200 | | 3 | 300 | | 4 | 400 | +----+--------+ 4 rows in set (0.00 sec)
这些查询真的效果一样?
如果你只需要第一个表中的数据的话,这些查询会返回相同的结果集。有一种情况就是,如果你从 LEFT JOIN的表中检索数据时,查询的结果就不同了。
如前所属,WHERE 子句是在匹配阶段之后用来过滤的。
例如: mysql> SELECT * FROM product a LEFT JOIN product_details b ON a.id=b.id AND b.weight!=44 AND b.exist=1 WHERE b.id is null; +----+--------+------+--------+-------+ | id | amount | id | weight | exist | +----+--------+------+--------+-------+ | 1 | 100 | NULL | NULL | NULL | | 2 | 200 | NULL | NULL | NULL | | 3 | 300 | NULL | NULL | NULL | | 4 | 400 | NULL | NULL | NULL | +----+--------+------+--------+-------+ 4 rows in set (0.00 sec) mysql> SELECT * FROM product a LEFT JOIN product_details b ON a.id=b.id WHERE b.id IS NULL OR b.weight=44 OR b.exist=0; +----+--------+------+--------+-------+ | id | amount | id | weight | exist | +----+--------+------+--------+-------+ | 1 | 100 | NULL | NULL | NULL | | 2 | 200 | 2 | 22 | 0 | | 3 | 300 | NULL | NULL | NULL | | 4 | 400 | 4 | 44 | 1 | +----+--------+------+--------+-------+ 4 rows in set (0.00 sec)
总附注:
如果你使用 LEFT JOIN 来寻找在一些表中不存在的记录,你需要做下面的测试:WHERE 部分的 col_name IS NULL (其中 col_name 列被定义为 NOT NULL),MYSQL 在查询到一条匹配 LEFT JOIN 条件后将停止搜索更多行(在一个特定的组合键下)。
数据库
2019-05-24 10:41:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
窗口-->首选项:
点击“编辑”之后,字体大小设为11的大小即比较合适。
数据库
2019-05-23 15:23:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
报错信息如下: java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:963) ~[mysql-connector-java-5.1.39.jar:5.1.39] at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:896) ~[mysql-connector-java-5.1.39.jar:5.1.39] at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:885) ~[mysql-connector-java-5.1.39.jar:5.1.39] at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:860) ~[mysql-connector-java-5.1.39.jar:5.1.39] at com.mysql.jdbc.ResultSetRow.getTimestampFast(ResultSetRow.java:937) ~[mysql-connector-java-5.1.39.jar:5.1.39] at com.mysql.jdbc.ByteArrayRow.getTimestampFast(ByteArrayRow.java:130) ~[mysql-connector-java-5.1.39.jar:5.1.39] at com.mysql.jdbc.ResultSetImpl.getTimestampInternal(ResultSetImpl.java:5946) ~[mysql-connector-java-5.1.39.jar:5.1.39] at com.mysql.jdbc.ResultSetImpl.getTimestamp(ResultSetImpl.java:5616) ~[mysql-connector-java-5.1.39.jar:5.1.39] at com.mysql.jdbc.ResultSetImpl.getTimestamp(ResultSetImpl.java:5645) ~[mysql-connector-java-5.1.39.jar:5.1.39] at com.zaxxer.hikari.pool.HikariProxyResultSet.getTimestamp(HikariProxyResultSet.java) ~[HikariCP-2.7.8.jar:na] at org.hibernate.type.descriptor.sql.TimestampTypeDescriptor$2.doExtract(TimestampTypeDescriptor.java:84) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:47) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:261) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:257) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.custom.ScalarResultColumnProcessor.extract(ScalarResultColumnProcessor.java:54) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.custom.ResultRowProcessor.buildResultRow(ResultRowProcessor.java:83) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.custom.ResultRowProcessor.buildResultRow(ResultRowProcessor.java:60) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.custom.CustomLoader.getResultColumnOrRow(CustomLoader.java:409) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:761) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.Loader.processResultSet(Loader.java:991) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.Loader.doQuery(Loader.java:949) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.Loader.doList(Loader.java:2692) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.Loader.doList(Loader.java:2675) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2507) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.Loader.list(Loader.java:2502) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2161) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:1016) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:152) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1414) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.query.Query.getResultList(Query.java:146) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at com.jingxuan.dao.AllDaoImpl.getCommodity(AllDaoImpl.java:111) ~[classes/:na] at com.jingxuan.dao.AllDaoImpl$$FastClassBySpringCGLIB$$bb7fcecc.invoke() ~[classes/:na] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:747) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE] at com.jingxuan.dao.AllDaoImpl$$EnhancerBySpringCGLIB$$c8de7df4.getCommodity() ~[classes/:na] at com.jingxuan.service.impl.AllServiceImpl.getAllCommodity(AllServiceImpl.java:56) ~[classes/:na] at com.jingxuan.controller.AllController.getAllCommodity(AllController.java:41) ~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_191] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_191] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_191] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_191] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.29.jar:8.5.29] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496) [tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.29.jar:8.5.29] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.29.jar:8.5.29] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_191] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_191] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.29.jar:8.5.29] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_191]
原因
因为“0000-00-00 00:00:00”在mysql中是作为一个特殊值存在的但 java.sql.Date 将其视为 不合法的值 格式不正确,这才是报错的原因
解决办法 spring: datasource: driver-class-name: com.mysql.jdbc.Driver username: XXXXX password: XXXXX url: jdbc:mysql://localhost:3306/XXXXX?characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
在url后面加上 zeroDateTimeBehavior=convertToNull
数据库
2019-05-23 10:39:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
1. 查询所有字段
select * from 表名;
2. 查询自定字段
select 字段名 from 表名;
3. 查询指定数据
select * from 表名 where 条件;
4. 带关键字IN的查询
select * from 表名 where 条件 [not] in(元素1,元素2);
5. 带关键词BETWEEN...AND...
select * from 表名 where 条件 [not] between 取值1 and 取值2;
6. 带like的字符匹配查询
like属于常用的比较运算符,实现模糊查询。它有通配符"%"和"_"。
select * from 表名 where 条件 like "%取值%";
在工作中的我们也常用 concat()函数来拼接字段和通配符
select * from 表名 where 条件 like concat('%',取值,'%');
7. 用关键字IS NULL查询空值
select * from 表名 where 条件 is [not] null;
8. 带AND的多条件查询
select * from 表名 where 条件1 and 条件2;
这里的条件可以是上面的任何一种,相当于逻辑运算的&&
9. 带关键词OR的多条件查询
select * from 表名 where 条件1 or 条件2;
相当于逻辑运算的||
10. 用关键词DISTINCT去除结果中的重复行
seelct distinct 字段名 from 表名;
11. 用关键词ORDER BY对查询结果进行排序
select * from 表名 order by 字段 [ASC|DESC];
12. 用关键词GROUP BY分组查询
select * from 表名 group by 字段;
可以多字段分组,但是会对后面的字段分组,再对前面的字段细微分组
13. 用关键词LIMIT限制查询结果的数量 看前面n条数据
select * from 表名 limit n; 看从m开始的n条数据(下标从0开始)
select * from 表名 limit m,n;
14. 聚合函数 count() 统计个数 sum() 某个字段的总数(null值除外) avg() 某个字段的平均值 max() 某个字段最大值 min() 某个字段最小值
15. 链接查询 内连接查询
内连接查询其实就是我们平常的多表查询 外连接查询
外连接包含左外连接(left join)和右外连接(right join)。
左外连接:将坐标的所有数据分别与右表中的每条数据进行连接组合,返回结果除内连接数据外还有左表不符合条件的数据,并在右表的相应列添加null值。 ps:内连接和外连接最大的区别就是内链接查询将会把两张表条件为null或者另一张表不存在的不显示,而外连接是会将左表或者右表都显示。
16. 子查询
子查询就是select查询的是另一个查询的附属。 带关键字IN的子查询 带比较运算符的子查询 带关键字EXISTS的子查询
关键字EXISTS时,内层查询语句不返回查询记录。而是返回一个真假值。
例如:select * from tb_row where exists (select * from tb_book where id=27);
这里是查询tb_book表中存在id值为27是否存在,存在则查询tb_row的所有行。 带关键字ANY的子查询
关键字ANY表示满足其中任意一个查询条件。
例如:select * from tb_book where row < ANY(select row from tb_row);
表示查询tb_book表中row比tb_row中任何row都小的行数据。 带关键字ALL的子查询
关键字ALL表示满足所有的条件。使用关键字ALL时,只满足 内层查询语句返回的所有结果才能执行外层查询语句。 例如:select * from tb_book where row>=ALL(select row from tb_row);
表示查询tb_book表中row字段的值大于tb_row表中的row字段的最大值的记录。
17. 合并查询结果 union union all ps:union和union all的差别就是union会去除相同的记录,而union all会知识简单的把结果合并到一起。
18. 定义表和字段的别名 为表取别名
可以使用 直接在真表名和别名之间加一个空格。 为字段取别名
可以使用空格或者 as 关键字。
19. 使用正则表达式查询 字段名 regexp '匹配方式'
模式字符 含义 应用举例
^ 匹配以特定字符或者字符串开头的记录 查询以java开头的记录
select * from tb_book where books regexp '^java'
$ 匹配以特定字符或字符串结尾的记录 查询以模块结尾的记录select * from tb_book where books regexp '模块$'
. 匹配字符串的任意一个字符,包括回车和换行符 查询包含P字符的记录select * from tb_book where books regexp 'P.'
[字符集合] 匹配“字符集合”中的任意一个字符 查询包含PCA字符的记录select * from tb_book where books regexp '[PCA]'
[^字符集合] 匹配除“字符集合”以外的任意一个字符 查询包含c~z字母以外的记录select * from tb_book where books regexp '[^c-z]'
s1竖线s2竖线s3 匹配S1、S2、S3中任意一个字符串 查询包含php、c、java中任意一个的记录select * from tb_book where books regexp 'php竖线c竖线java'
* 匹配多个该符号之前的字符,包括0和1个 查询A字符前出现过J的记录select * from tb_book where books regexp 'J*A'
+ 匹配多个该符号之前的字符,包括1个 查询在A字符前至少出现过一个J的记录select * from tb_book where books regexp 'J+A'
字符串{N}
字符串{M,N}
匹配字符串出现多次
匹配字符串出现至少M次,最多N次
查询a字符出项3次的记录select * from tb_book where books regexp 'a{3}'
查询A字符出现2-4次的记录select * from books regexp 'a{2,4}'
数据库
2019-05-22 23:56:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
点开题目是不是有点懵X,因为你只知道insert...values这一种,重来没有听说过三种,现在来介绍一下。
插入数据三种方式: insert into 表名(字段名) values(插入值); 最常用的插入语句 insert into 表名 set 字段名=插入值; 根据字段一个一个插入 insert into 表名(字段名) select 字段名 from 另一张表;从另一张表获取值插入表
修改数据一种方式: update 表名 set 字段名=修改值 where 条件;
删除数据的两种方式 delete from 表名 where 条件;删除的条件应该具有unique的属性,避免删错 在真实项目中我们通常是使用逻辑删除,如给表增加字段is_del,当删除时就给is_del修改为0; 但是有时我们想要删除表中的所有数据,但是又想保留表结构,所以可以使用 truncate table 表名;
数据库
2019-05-22 23:23:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
MYSQL 软件概念 MYSQL是一款数据库,关系型数据库系统; MYSQL主要用于存放:员工姓名、身份证ID、商城订单及金额、销售业绩及报告,学生考试成绩、网站帖子、论坛用户信息等; MYSQL在WEB架构中,不是孤立存在,作用于WEB后端,存储WEB产生的数据; 典型互联网架构应用中,MYSQL用于LAMP、LEMP、LNMP架构中,主要用于数据存储; MYSQL是关系型数据库系统,关系型数据库特点:

MYSQL主从用途 MYSQL主从,有主库和从库,内容一般是一致,master/slave; 假设LAP(Linux+Apache+PHP)+MYSQL(单台),MYSQL属于单点故障,一旦MYSQL宕机,整合网站无法访问; 为了解决单点问题,引入MYSQL从库,从而保证网站数据库不宕机或者宕机之后能够快速恢复; MYSQL主从,主库和从库一定保持一致,如何保证主从数据一致? MYSQL主从架构,可以协助实现数据库读写分离,从而保证网站更加的稳定和可靠;

MYSQL 主从原理 MYSQL主从复制是一个异步复制过程,整个过程需要开启三个线程,分别是master开启I/O线程,Slave上开启I/O线程和SQL线程; Slave上启动start slave,启动I/O线程,基于I/O连接到master数据库,告诉Master服务器,我要请求指定bin-log文件、position点之后的内容; Master数据库接收Slave发送的请求,通过I/O线程去响应,将bin-log文件中内容发给Slave数据库; Slave数据库接收到master传递的数据内容,存储到本地的relay-log中继日志中,生成一个master.info文件,该文件内容包含此次同步的master端bin-log名称、position点、master ip、端口、用户名、密码等; Slave库SQL实时运行的,SQL检测到relay-log日志内容有更新,解析更新的内容,解析成SQL语句,将SQL语句拿到Slave数据库中去执行; SQL线程执行完毕,效果跟主库数据保持一致,从而实现数据备份、数据冗余;

MYSQL bin-log 用途 bin-log日志最大的功能记录数据库增、删、改、插入等操作,记录用户操作的SQL语句; bin-log日志可以用数据增量备份、完整备份; bin-log还可以主要主从复制+读写分离; MYSQL主从实战 MYSQL高可用实战

MySQL数据库导入数据 和 导出数据的m

查看系统环境变量的命令e'nü


数据库
2019-05-22 16:22:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
比如有一张表:signals_120628
想把这种表的数据快速的导入到分区表signals,方法如下:
ALTER TABLE SIGNALS EXCHANGE PARTITION P120628 WITH TABLE signals_120628;
花了 26秒。
Executed in 26.437 seconds
SQL> select count(*) from SIGNALS partition(P120628);
COUNT(*)

3803257
数据库
2019-05-22 16:17:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 作者介绍: 陈东明,饿了么北京技术中心架构组负责人,负责饿了么的产品线架构设计以及饿了么基础架构研发工作。曾任百度架构师,负责百度即时通讯产品的架构设计。具有丰富的大规模系统构 建和基础架构的研发经验,善于复杂业务需求下的大并发、分布式系统设计和持续优化。个人微信公众号 dongming_cdm。
Tedis ( https://github.com/eleme/tedis) 是基于开源 TiKV 的兼容 Redis 协议的强一致性的 NoSQL 数据库开源项目。 本文介绍一下 Tedis 开源项目的架构设计和特性,以及架构背后的一些思考(包括为何选择 TiKV 和 Redis 协议)。
先来讨论为什么基于 TiKV 构建我们自己的 NoSQL 数据库。
首先简述一下 TiKV[1],TiKV 是 TiDB 的一个子项目,TiDB 是一个分布式的关系型数据库 [2],TiKV 是 TiDB 的存储层。TiKV 本身是可独立于 TiDB 的单独项目。它是一个强一致、可水平扩展的、高可用的分布式 Key-Value 存储系统。
选择 TiKV 的第一个原因是 TiKV 是一个强一致的系统。 在我的另外一篇文章中(发表在 InfoQ, 参看  https://www.infoq.cn/article/rhzs0KI2G*Y2r9PMdeNv  ),我阐述了一个观点:NoSQL 数据库应该具有一致性,并且通过多副本技术达到实际的高可用,也就是说 NoSQL 数据库应该是一个“实际上的 CA” (effectively CA)系统。但是在这篇文章中我并没有明确说明 NoSQL 该具有的一致性是哪种一致性。 实际上,我所说的一致性其实就是一种强一致性  [3], 或者更准确的说是线性一致性  [4]。TiKV 正是具有这种线性一致性。TiKV 中的每个数据都会保存 3 个副本,在只有一个副本的节点宕机或者出现网络分区的情况下,另外 2 个副本仍然能够对外提供服务。理论上来讲,同时出现 2 个以上副本同时坏掉的可能性很小,也就是理论上可以达到非常高的可用性。通过 TiKV 滚动升级等运维辅助,如果在实际的生产中,有良好的运维,可以达到实际上非常高的可用性。也就是称为一个“实际上的 CA”(effectively CA)系统。
TiKV 通过 Raft [5] 协议实现了线性一致性和高可用 2 个特性。Raft 是一种分布式共识协议,通过 Raft 协议,数据可以被认为是原子的写入到 3 个副本上。共识协议的一个特点就是要写入大多数,才会认为写入成功,3 个副本的大多数就是 2 个,也就是在只有一个副本宕机或者网络分区的情况下,仍然可以成功写入,并且提供读服务。
选择 TiKV 的第二个原因是 TiKV 的架构可扩展和生态。 在 TiDB 中 TiKV 是独立的一层,形成了一个很好的可扩展架构,实际上可以在 TiKV 上扩展出很多不同的数据库出来。TiDB 层本身就是这种架构上的一个扩展。这种架构类似于 Google 公司的第一代的 Spanner 系统 [6],Spanner 系统本身也是一个强一致性的、高可用的分布式 Key-Value 系统。在 Spanner 的基础之上,Google 构建了 F1 系统 [7],实现了 SQL 协议。2017 年,Google 升级了 Spanner 到第二代 [8],让 Spanner 本身就具有了 SQL 能力。虽然一代 Spanner+F1 是这样的架构,但它仍然是一种非常优秀的架构。我们的 Tedis 项目,也是构建在这一可扩展架构上的一个项目,依托于 TiKV 提供的底层能力,向上构建了不同于 SQL 协议的 Redis 协议。 我相信 TiKV 的这种可扩展架构,未来可以成为一种生态,还可以在上面“⻓出”其他的类型的数据库,比如说 Mango 协议、图协议。这些数据库都具有与底层 TiKV 相同的线性一致性和高可用性,区别只在于对外的接口协议不同。 目前这种生态已初⻅端倪,Titan( https://github.com/distributedio/titan)  这个开源项目,与我们的 Tedis 项目非常类似,他们的开源步伐先于我们,目前做的也非常不错。我相信,我们肯定不是这个生态中的最后一个。
总之基于 TiKV,Tedis 实现了以下的技术特性:
1. 大数据量,可以存储至少数十 TB 级别的数据。
2. 高性能,在满足高 QPS 的同时,保证比较低的延时。
3. 高可靠,数据被可靠的持久化存储,少量机器的损坏不会导致数据的丢失。
4. 高可用,作为在线服务的底层依赖存储,要有非常完善的高可用性能力,外卖服务不同于电子商务,对实时性要求非常高,对系统的可用性的要求则是更高的。
5. 易运维,可以在不停服的基础上进行数据迁移和集群扩容。
接下来,我们讨论第二个问题,为什么选择 Redis 协议。
SQL 语言与其背后的关系模型,从 1970s 发明以来,一直在应用开发领域占据这统治地位,虽然在 CAP 定理的推动下 [4],在 NoSQL 运动中,出现很多 NoSQL 系统,就如我前面阐述的一样,一致性不应该是 NoSQL 出现的理由,去 SQL 和关系模型才是 NoSQL 出现的动力。但我并不认为 NoSQL 会代替 SQL。虽然 NoSQL 出现的时候,原本表达的意思是 “NO SQL (没有 SQL) ” ,但是我觉得另外一种对 NoSQL 的解释更合适,也就是“ N ot  O nly  SQL ( 不仅仅有 SQL )”。NoSQL 不是 SQL 的替代品,应该是 SQL 的有力补充。在 NoSQL 运动中,涌现出来的非常优秀的 NoSQL 系统大多都有自己的独有的接口协议,比如 Redis、MongoDB、Cassandra、图数据库等等。他们都有各自非常适用的使用场景,比如 MongoDB 贴近面向对象,图数据库适合节点的图关系运算。而 Redis 贴近开发者数据结构思维,相信每个开发者都是从数组、hash 表、队列这样的数据结构中成⻓起来的。
另外,Redis 本身是一个非常优秀的产品,它的普及程度非常高,特别是在互联网行业。在每个互联网公司,Redis 都已经成为工程师开发工具箱中,必备的工具之一。Redis 已经是开发者除 SQL 之外,第二熟悉的产品了。
但是,选择 Redis 协议,也给我带来一些实际的困扰,我们有些使用者最初接触 Tedis 时,总是拿我们和 Redis 相比。但是,虽然我们采用的是 Redis 接口,但是  Tedis 本身并不对标 Redis 这个产品。Redis 是非常优秀的缓存。虽然 Redis 也可以开启持久化功能,由于 Redis 本身架构设计,开启持久化的 Redis 仍然不能达到“实际上的 CA”(effectively CA),和 100% 的持久性(durability)。这是 Redis 和 Tedis 的一个很大的区别,Tedis 是一个数据库,不是一个缓存。
讨论完上面的 2 个架构思考,我们来看一下 Tedis 的架构设计。
在 Tedis 中,我们封装了一个 TiKV 的 SDK,对 Redis 的协议进行了解析,并且将 Redis 协议转成对 TiKV 的调用。
目前 Tedis 仍然有很多要完善的地方,但是我们会尽快完善如下的事项,在我们的开源日程表中:
1. Redis 命令的补全
2. 压缩和限流等一些扩展功能
3. Cassandra 协议的支持
写在最后
作为存储系统,不应该让使用者在一致性、可用性这些技术特性上做过多的选择,使用者应该更多的考虑哪种接口更适合自己的应用场景,自己更熟练使用哪种接口,能用哪种接口更快的进行功能开发。
由于篇幅所限,本文中关于强一致性、线性一致性、Redis、Raft、Spanner 的很多技术细节的阐述未能详尽,拟另行成文讨论。
参考资料: https://github.com/pingcap/tikv https://github.com/pingcap/TiDB Eventually Consistent - Revisited,Werner Vogels, 2008, http://www.allthingsdistributed.com/2008/12/event ually_consistent .html Linearizability: A Correctness Condition for Concurrent Objects,Maurice P. Herlihy and Jeannette M. Wing,1990 In Search of an Understandable Consensus Algorithm, Diego Ongaro and John Ousterhout, 2014 Spanner: Google’s Globally-Distributed Database, James C. Corbett, Jeffrey Dean et al., 2012 F1: A Distributed SQL Database That Scales, Jeff Shute et al., 2013 8.Spanner: Becoming a SQL System, David F. Bacon et al., 2017
数据库
2019-05-22 10:19:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Win10安装MySQL5.7.22 解压缩版(手动配置)方法
数据库
2019-05-22 09:16:00
「深度学习福利」大神带你进阶工程师,立即查看>>> multi后不能执行get,没有结果返回的 也不能redirected,否则exec不行 132.120.2.134:26000> MULTI OK 132.120.2.134:26000> get abc QUEUED 132.120.2.134:26000> GET ABC -> Redirected to slot [14740] located at 132.120.2.135:26001 (nil) 132.120.2.135:26001> SET ABC 2 OK 132.120.2.135:26001> GETSET (error) ERR wrong number of arguments for 'getset' command 132.120.2.135:26001> EXEC (error) ERR EXEC without MULTI
set如果redirected同样不行 132.120.2.135:26001> multi OK 132.120.2.135:26001> set abc 1 -> Redirected to slot [7638] located at 132.120.2.134:26000 OK multi可以小写,命令不区分大小写。 但是key区分。abc和ABC不同。 如果先set,再expire,可用set EX代替事务 132.120.2.134:26000> set abc 212 EX 30 OK
数据库
2019-05-22 09:14:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
在MySQL中,常见的过程式SQL语句可以用在存储体中。其中包括IF语句、CASE语句、LOOP语句、WHILE语句、ITERATE语句和LEAVE语句,它们可以进行流程控制。 IF语句相当于Java中的if()...else if()...else... CASE语句相当于Java中的switch()...case A:...break;default... LOOP语句相当于Java中的while(true){...} while语句相当于Java中的while(条件){...} REPEAT语句相当于Java中的do{...}while(条件) LEAVE语句相当于Java中的 break; 配合LOOP使用 当REPEAT出现在LOOP、REPEAT、WHILE语句中的时,相当于Java中的continue;
1. IF语句
列一: DELIMITER// CREATE PROCEDURE example_if(IN X INT) BEGIN IF X=1 THEN SELECT 1; ELSEIF X=2 THEN SELECT 2; ELSE SELECT 3; END IF; END // 注意这里的selimiter//后面的 “//”和最后的 “//”
这样在当前数据库中究生成了过程控制函数example_if(x)
使用流程为 CALL example_if(6);
2. CASE语句
列二: DELIMITER// CREATE PROCEDURE example_case(IN X INT) BEGIN CASE X WHEN 1 THEN SELECT 1; WHEN 2 THEN SELECT 2; ELSE SELECT 3; END CASE; END //
这样在当前数据库中究生成了过程控制函数example_case(x)
使用: CALL example_case(7);
3. WHILE语句
列三: DELIMITER// CREATE PROCEDURE example_while(OUT SUM INT) BEGIN DECLARE i INT DEFAULT 1; DECLARE s INT DEFAULT 0; WHILE i<=100 DO SET s=s+i; SET i=i+1; END WHILE; SET SUM=s; END //
这样在当前数据库中究生成了过程控制函数example_while(x)
调用: CALL example_while(@a); SELECT @s;
4. LOOP语句
列四: DELIMITER// CREATE PROCEDURE example_loop(OUT SUM INT) BEGIN DECLARE i INT DEFAULT 1; DECLARE s INT DEFAULT 0; loop_label:LOOP SET s=s+i; SET i=i+1; IF i>100 THEN LEAVE loop_label; END IF; END LOOP; SET SUM=s; END //
这里的leave label相当于java中的break;
调用: CALL example_loop(@s); SELECT @s;
5. REPEAT语句
列五: DELIMITER// CREATE PROCEDURE example_repeat(OUT SUM INT) BEGIN DECLARE i INT DEFAULT 1; DECLARE s INT DEFAULT 0; REPEAT SET s=s+i; SET i=i+1; UNTIL i>100 END REPEAT; SET SUM=s; END //
调用: CALL example_repeat(@s); SELECT @s;
数据库
2019-05-21 23:14:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
最近迁移一个数据库,500多张表大概600多万条数据,通过navicat导出的数据,再通过source命令导入到mysql8.0
之前也做过类似的工作,但是却从来没有这么慢过,一个小时了还没有完成,之前在笔记本上做相同的数据量大概也就5分钟搞定,不过笔记本上跑的是mariadb,也做过其他机器的试验,都是mysql5.*。猜测的原因一是目标机的mysql8.0做了主备,redo.log太厉害一直在写,二是数据导出的方式不对,或许应该用mysqldump加参数优化一下。通过查看系统资源占用情况,mysql并没有占用多高,系统相对来说很空闲,机器性能也完全够用。稍后查日志分析下原因
数据库
2019-05-21 20:45:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
(8)SELECT (9) DISTINCT
(1) FROM
(3)JOIN
(2) ON
(4) WHERE
(5) GROUP BY
(6) WITH {CUBE|ROLLUP}
(7) HAVING
(10)ORDER BY
(11)LIMIT
注意:每个操作都会产生一张虚表,该虚表作为一个处理得输入。这些虚表对用户事透明得
数据库
2019-05-21 17:49:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
SELECT t.building,t.unit,t.room,t.ashcan
,(SELECT COUNT(a.resident_id) from t_address_book a
where a.village_id = t.village_id AND a.building = t.building
and a.room = t.unit and a.house = t.room
and a.`status` = 1
) AS regisNum
from t_village_standard t
where t.village_id = 317
and t.`status` = 1
数据库
2019-05-21 17:42:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
用途:
GROUP BY 语句用于 对一个或多个列对结果集进行分组。
例子:
原表:
现在,我们希望根据USER_ID 字段进行分组,那么,可使用 GROUP BY 语句。
我们使用下列 SQL 语句:
SELECT ID,USER_ID,problems,last_updated_date from t_iov_help_feedback GROUP BY USER_ID;
结果集类似这样:
可以看到上面的,结果的确是根据 USER_ID 进行分组了,但是返回的记录是 USER_ID 对应的每组 中最小的那条记录。也就是ID最小的那条。
现在我想分组后得到,last_updated_date 最大的那条记录。这怎么实现呢?
很简单,直接查询的表默认是以 ID 进行顺序排序的,因为分组的时候取的是每组中的第一条。所以只需要 使查询的表 按照 last_updated_date
倒叙排序就行了。
实现的SQL如下,这里使用了嵌套查询。
SELECT ID,USER_ID,problems,last_updated_date FROM (select * from t_iov_help_feedback order by USER_ID, LAST_UPDATED_DATE DESC) b
GROUP BY b.USER_ID;
其中:select * from t_iov_help_feedback order by USER_ID, LAST_UPDATED_DATE DESC 就相当于一个按照USER_ID升序, last_updated_date
倒叙排序的表了。
查询结果如下:
现在取的就是每组中时间最大的那条记录了。
当遇到两个不同的表时,可以使用以下SQL:
select a.title, t.name, t.price from a
inner join (select * from b order by id, price ) t on t.id = a.b_id
group by a.b_id;
---------------------
作者:zhang_wt
来源:CSDN
原文:https://blog.csdn.net/u012660464/article/details/78605078
版权声明:本文为博主原创文章,转载请附上博文链接!
数据库
2019-05-19 16:26:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
MySQL 的 case when 的语法有两种:
1.简单函数 (比较col_name和when后面的值是否相等) CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END

2.搜索函数 (判断when后面的表达式expr是否为true,如果为true,则返回result1) CASE WHEN [expr] THEN [result1]…ELSE [default] END
两种语法的区别
简单函数 CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END: 枚举这个字段所有可能的值 SELECT NAME '树名', CASE NAME WHEN '桃树' THEN '桃花' WHEN '梨树' THEN '梨花' WHEN '芙蓉' THEN '莲花' ELSE '无名花' END '花名' FROM tree_info;
查询结果:
搜索函数
CASE WHEN [expr] THEN [result1]…ELSE [default] END :搜索函数可以写判断,并且搜索函数只会返回第一个符合条件的值,其他 case 被忽略 SELECT age '年龄段', CASE WHEN age <= 10 THEN '不愁' WHEN age <= 20 THEN '不悔' WHEN age <= 30 THEN '而立' WHEN age <= 40 THEN '不惑' WHEN age <= 50 THEN '知天命' WHEN age <= 60 THEN '耳顺' ELSE '年级大了' END '状态' FROM age_info;
查询结果:
特殊用法
1.聚合函数 sum 配合 case when 的简单函数实现行转列
表1:courses
表2:score
表3:student:
测试: SELECT st.stu_id '学号', st.stu_name '姓名', SUM( CASE co.course_name WHEN '语文' THEN sc.scores ELSE 0 END ) '语文', SUM( CASE co.course_name WHEN '数学' THEN sc.scores ELSE 0 END ) '数学', SUM( CASE co.course_name WHEN '物理' THEN sc.scores ELSE 0 END ) '物理', SUM( CASE co.course_name WHEN '化学' THEN sc.scores ELSE 0 END ) '化学', SUM( CASE co.course_name WHEN '生物' THEN sc.scores ELSE 0 END ) '生物', SUM( CASE co.course_name WHEN '历史' THEN sc.scores ELSE 0 END ) '历史' FROM student st LEFT JOIN score sc ON st.stu_id = sc.stu_id LEFT JOIN courses co ON co.course_no = sc.course_no GROUP BY st.stu_id ORDER BY NULL;
测试结果:
一般我们查找的时候,根据stu_id分组,例如: SELECT st.stu_id '学号', st.stu_name '姓名', GROUP_CONCAT(sc.scores),GROUP_CONCAT(sc.`course_no`),GROUP_CONCAT(co.`course_name`) FROM student st LEFT JOIN score sc ON st.stu_id = sc.stu_id LEFT JOIN courses co ON co.course_no = sc.course_no GROUP BY st.stu_id ORDER BY NULL;
查询结果:
这样的查询结果并不如例如case when 的行转列数据清晰
2.把一行拆分为多了的示例 SELECT SipAccount, COUNT(1) AS number,IsCheck FROM cdr GROUP BY SipAccount,IsCheck
针对这个统计结果进行拆分(0表示未打分,1代表优秀,2代表合格,3代表不合格)
想要的最终结果如下:
所以最终要用到行拆分成三列,语句如下 SELECT SipAccount, (CASE IsCheck WHEN 1 THEN number END) youxiu, (CASE IsCheck WHEN 2 THEN number END) hege, (CASE IsCheck WHEN 3 THEN number END) buhege FROM (SELECT SipAccount, COUNT(1) AS number,IsCheck FROM cdr GROUP BY SipAccount,IsCheck) AS a
现在结果是这样的,你会发现虽然拆成了三列,但是最终结果还不是自己需要的,接下来就需要根据sipaccount来分组的同时对结果进行处理了。语句如下: SELECT sipaccount, IF(MAX(youxiu) IS NULL,0, MAX(youxiu)) youxiu, IF(MAX(hege) IS NULL,0, MAX(hege)) hege, IF(MAX(buhege) IS NULL,0, MAX(buhege)) buhege FROM (SELECT SipAccount, (CASE IsCheck WHEN 1 THEN number END) youxiu, (CASE IsCheck WHEN 2 THEN number END) hege, (CASE IsCheck WHEN 3 THEN number END) buhege FROM    (SELECT SipAccount, COUNT(1) AS number,IsCheck FROM cdr GROUP BY SipAccount,IsCheck) AS a) AS b GROUP BY sipaccount
最终得到了这个结果。正式我们需要的格式
MySQL的IF函数(返回两个不同结果的时候用IF,如果返回多个不同的结果,用case when)
格式:IF(Condition,A,B)
意义:当Condition为TRUE时,返回A;当Condition为FALSE时,返回B。
3.mysql 使用Case When 达到排序的效果 SELECT DISTINCT dev.deviceId, dev.deviceTypeCode, dev.mcuID, dev.workState, dtf.dcTypeCode from devicebase dev ORDER BY CASE dev.workstate WHEN '3' THEN 0 WHEN '2' THEN 1 WHEN 'x' THEN 2 WHEN 'y' THEN 3 WHEN '1' THEN 4 ELSE 5 END, dev.workstate
或者 SELECT DISTINCT dev.deviceId, dev.deviceTypeCode, dev.mcuID, dev.workState, dtf.dcTypeCode, CASE dev.workstate WHEN '3' THEN 0 WHEN '2' THEN 1 WHEN 'x' THEN 2 WHEN 'y' THEN 3 WHEN '1' THEN 4 ELSE 5 END AS state from devicebase dev ORDER BY state
4.利用case when实现分组(在网上搜索case when的时候找到的其他示例)
1-4级为一组,5,6级为一组 ,5-6级的优先处理,之后在处理1-4级 SELECT * FROM t_automatic_assign t ORDER BY t.RETRIEVE_STATUS DESC, CASE WHEN DECISION_LEVEL = 5 OR DECISION_LEVEL = 6 THEN 1 ELSE 2 END t.CREATE_DATE ASC
5.利用case when实现细化分组
用户查询两个状态的列表,进行排序, 然后在第一个状态和第二个状态时按照lastLoginDate降序在第三个状态按照tokencreatetime升序 SELECT * FROM yun_user WHERE type IN(2,1,99) ORDER BY type ASC, CASE WHEN type = 2 OR type=1 THEN lastLoginDate END DESC, CASE WHEN type=99 THEN tokencreatetime END ASC;
6.摘自其他博客的一个实例
条件:某字段代表该数据的状态取值为非负整数,0表示无状态。
  需求:以该字段升序排序,同时需要将值为0的数据放在最后。
  首先我们看一下,表的结构:
  

  正常的使用升序查询结果是这样的:
  

  要让“小赤”排在最后,可以这样写:
  

  也可以这样:(mysql的除数为0,则值为null,不会报错)
  

  还可以使用 CASE WHEN 再不影响查询结果的前提下,改变排序的依据:
  
7.case when 返回的应该是一个字符串类型的,而不是实际的那个变量的值的类型,例如有表结构
score表中,scores的属性类型为float,数值如下:
按照分数scores排序: SELECT * FROM `score` ORDER BY `scores`
利用case when排序,以为case when的条件为false,所以实际上也是按照scores排序,但是和order by scores排序的结果集顺序不一致,如下图:
如果想使用case when 并且按照数字大小排序可以这么做,在case when 的返回值后面+0,即主动把case when的返回值变为数字类型:
case when的用法就总结到这里,如果有不对的地方,欢迎指正
数据库
2019-05-19 13:11:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
在很多情况下,例如windows系统下,并不想将mysql数据库以服务的形式安装,因为可能会用到多种版本的数据库,我们想下载多种版本数据库放在不同的目录下,在需要哪个版本的数据库的时候,启动相应的mysql服务即可,可以灵活切换。
1.在mysql官网下载压缩包
https://downloads.mysql.com/archives/community/ 在这里可以根据系统要求下载相应的版本,我这里以Mysql5.7.17为例,系统选择采用的是Windows 64位的,然后点击现在ZIP Archive
2.加压下载好的文件并添加配置文件my.ini
将下载好的文件加压到某个目录下,这里假设解压到了 D://mysql-5.7.17目录下。然后在改文件夹中找是否包含默认的配置文件my-default.ini,如果有的话只需要将改文件进行重命名,修改为my.ini即可
3.进行数据库的初始化
对于采用下载ZIP Archive文件来安装mysql,需要手动进行mysql的初始化。这是因为对于采用这种形式下载的mysql包中是没有data文件的,即数据库中没有任何数据,连登陆mysql的root用户都没有,所以我们首先要进行数据库数据的初始化。
方法很简单,只需要在命令行执行mysql解压目录下bin文件夹中的mysqld.exe即可,具体如下: D:\mysql-5.7.17\bin\mysqld.exe --initialize --user=root --console
这里使用了--initialize 表示在初始化的时候会给指定的root用户随机生成一个密码,命令中加上--console就是为了让在执行命令的时候打印出来这个密码,如下例子:
然后启动mysql服务之后就可以修改默认的密码: alter user root@'localhost' identified by 'root';
当然也可以使用如下命令: D:\mysql-5.7.17\bin\mysqld.exe --initialize-insecure --user=root --console
这里使用了--initialize-insecure 表示在初始化的时候不会给root用户生成密码,即在登录的时候是不需要密码就可以登录。最终对root用户密码的设置需要我们自己手动去设置,如: set password for root@localhost=password('root');
官方说明:
Use --initialize for “secure by default” installation (that is, including generation of a random initial root password). In this case, the password is marked as expired and you will need to choose a new one.
With --initialize-insecure, no root password is generated. This is insecure; it is assumed that you will assign a password to the account in timely fashion before putting the server into production use.
4.启动数据库
在windows系统中,只需要双击mysqld.exe文件,即可启动mysql。该启动方式启动之后会在后台运行,可以通过任务管理器来查看mysql是否启动成功。
5.使用客户端连接数据库
执行命令: D:\mysql-5.7.17\bin\mysql.exe -uroot -proot
即可连接数据库。
可以参考官方文档: https://dev.mysql.com/doc/refman/5.7/en/windows-install-archive.html
数据库
2019-05-18 14:57:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
现象一:数据库插入数据有中文时,报错:
原因:电脑的系统默认编码是gbk,而mysql客户端提供的编码方式是utf8,两种编码不一致导致的
查看当前mysql的编码:show variables like 'character%';如下图:

解决:将mysql提供的客户端编码变为gbk
设置客户端编码: set character_set_client = gbk;

现象二:此时可以插入中文数据了,但是在select * from user时发现刚才插入的中文数据乱码

原因:电脑的系统默认编码是gbk,而mysql结果集的编码方式是utf8,两种编码不一致导致的
解决:将mysql结果集编码设置成gbk
设置结果集的编码: set character_set_results = gbk;

再次查询数据库

注意: 上述操作只针对当前客户端有效
彻底修改编码的操作:在安装文件中寻找my.ini文件 找到default-character-set=utf8一行
将utf8改成gbk,意味着和客户端相关的编码全部改成gbk
再次查询编码集:
以后可以随意进行中文的存储于显示了
数据库
2019-05-18 12:21:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
如何使用Oracle分区功能?
1.个别场景不能从根本上提高查询速度 在Oracle10g时不支持自动生成分区,技术人员都是手动创建一年或者半年的分区或者当超过限制时把数据都load到最大值分区,但是一年半年过后要么出现数据无法插入或者某个分区数据剧增,这个时候出现了Oracle11g的自动分区功能,但是自动分区名称不能人为设置。如果说数据量过大或者出现跨分区查询会出现性能问题。 举个栗子:线上有一个日志储存系统,每天大概存储1000W左右的数据,支持分页排序并且按照日期查询功能(如果不排序,这个数据量对于Oracle是小ks)于是我们采用了分区+覆盖索引(如果想进一步了解.....)查询的的功能,性能稍微提升。但是一段时间后发现还是拖死系统。(因为这就是CAP问题,想从根本上解决问题,请建议公司采用nosql(habase、ELK)实现)。 如果有这样一种这样场景,工资小于等于5000,大于5000并且小于等于12000,大于12000并且小于25000,大于等于25000分别按照这些工资级别创建分区则非常高效,因为可以指定分区进行查询( select * from TBL_OPR_CNT partition(5000_part); ),因为指定分区查询,效率直接提升。 由此得知,关系数据库效率高低,在于我们如何发挥它的长处。
2. 手动对表进行move操作,或者删除表分区会导致索引失效 在实际线上环境,常常当发现性能出现问题时,这个时候才采取分区的解决方案,但是分区表一般都是全局索引,然后直接在原表采取分区功能,用了一段时间产生了历史分区数据,然后删除了其中一部分历史分区,发现数据无法插入了。如下错误: jdbc.exception.UncategorizedSQLException: uncategorized SQLException for SQL [insert into AUDITS(C_ID,N_PERSON_ID,C_NAME,C_CODE,C_DEPT,N_LOG_TIME,C_LOG_TYPE,C_CONTENT,C_RESULT,C_SN,N_DEPT_ID) values(?,?,?,?,?,?,?,?,?,?,?)]; SQL state [72000]; error code [1502]; ORA-01502: index 'AUDITS_PK' or partition of such index is in unusable state ; caused by: ORA-01502: index 'AUDITS_PK' or partition of such index is in unusable state
采取如下方法重建索引解决处理。 select index_name,index_type,tablespace_name,table_type,status from user_indexes where index_name='AUDITS_PK'; alter session set skip_unusable_indexes=false; alter index AUDITS_PK rebuild; commit;
3.其出现这个问题的根本原因和解决方法是什么呢? 移动或者删除表空间或者分区后,基于该table的索引会自动失效UNUSABLE;此时访问或操作该table时,会报ORA-01502异常;无论唯一还是普通索引都要通过重建解决。 解决方法:在使用表分区时尽量创建本地索引.( 例如: create index AUDITS_PK on AUDITS(id) local; --因为id是分区键,所以这样就创建了一个有前缀的本地索引) 这样在删除分区后则索引不会出现失效问题。
数据库
2019-05-17 21:39:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
首先考虑使用缓存来处理,如果缓存不够用,再使用读写分离来实现
application.yml配置两个数据源 #默认使用配置 spring: profiles: active: dev --- #开发配置 spring: profiles: dev datasource: master: jdbc-url: jdbc:mysql://localhost:3812/test username: user password: pwd driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource slave: jdbc-url: jdbc:mysql://localhost:3812/test username: user password: pwd driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource
Application.java 注意Mapper上加@Mapper注解,然后可以被扫描到 @SpringBootApplication @EnableAutoConfiguration @MapperScan("com.xx.mobile.group.dao") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
DataSourceConfig.java 注意有三个DataSource @Configuration public class DataSourceConfig { @Bean @ConfigurationProperties("spring.datasource.master") public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } @Bean @ConfigurationProperties("spring.datasource.slave") public DataSource slave1DataSource() { return DataSourceBuilder.create().build(); } @Bean public DataSource myRoutingDataSource(@Qualifier("masterDataSource") DataSource masterDataSource, @Qualifier("slave1DataSource") DataSource slave1DataSource) { Map targetDataSources = new HashMap<>(); targetDataSources.put(DBTypeEnum.MASTER, masterDataSource); targetDataSources.put(DBTypeEnum.SLAVE, slave1DataSource); DataSourceRouting myRoutingDataSource = new DataSourceRouting(); myRoutingDataSource.setDefaultTargetDataSource(masterDataSource); myRoutingDataSource.setTargetDataSources(targetDataSources); return myRoutingDataSource; } }
DBType public enum DBTypeEnum { MASTER, SLAVE; }
MybatisConfig 注意注入的DataSource,注意事务注解的order @EnableTransactionManagement(order = 2) @Configuration public class MyBatisConfig { @Resource(name = "myRoutingDataSource") private DataSource myRoutingDataSource; @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(myRoutingDataSource); sqlSessionFactoryBean.setMapperLocations( new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml")); return sqlSessionFactoryBean.getObject(); } @Bean public PlatformTransactionManager platformTransactionManager() { return new DataSourceTransactionManager(myRoutingDataSource); } }
DataSourceRouting public class DataSourceRouting extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DBContextHolder.get(); } }
DBContextHolder public class DBContextHolder { private static final ThreadLocal contextHolder = new ThreadLocal<>(); private static final AtomicInteger counter = new AtomicInteger(-1); public static void set(DBTypeEnum dbType) { contextHolder.set(dbType); } public static DBTypeEnum get() { return contextHolder.get(); } public static void master() { set(DBTypeEnum.MASTER); System.out.println("切换到master"); } public static void slave() { set(DBTypeEnum.SLAVE); System.out.println("切换到slave"); } }
使用从库注解UseSlaveDatabase public @interface UseSlaveDatabase { }
DataSourceAop 注意此切面的Order @Aspect @Component public class DataSourceAop implements Ordered{ @Override public int getOrder() { return 0; } @Before("readPointcut()") public void read() { DBContextHolder.slave(); } @Pointcut("@annotation(com.xx.mobile.config.UseSlaveDatabase)") public void readPointcut() { } }
测试类 @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) public class TestTask { @Autowired private ITaskService taskService; @Test public void save() throws Exception { } @Test public void query() throws Exception { //query方法可以用上面的注解 } }
相关的service dao mapper entity没有写 原理:多个数据源汇集到一个数据源上(myRoutingDataSource),然后定义切面,遇到有UseSlaveDatabase注解就设置数据源为从库,默认使用主库,因为 myRoutingDataSource.setDefaultTargetDataSource(masterDataSource); 注意数据源选择要在是事务之前,所以切面的order要注意。
数据库
2019-05-17 19:58:00
「深度学习福利」大神带你进阶工程师,立即查看>>>

grid安装的时候,进行到operating system groups 步骤,oracle asm operator(osoper for asm)group (optional) 不管是选dba还是asmoper都报错


【ins-30060】check foe group exisetence faied,如何把选项置为空,则能通过,如何解决?


安装grid infrastructure时,在创建用户、组、目录部分建议按照oracle官方文档来,不然在安装grid和之后dbca建库(如果采用asm)时可能会碰到问题。
建组
# groupadd oinstall
# groupadd dba
# groupadd oper
# groupadd asmadmin
# groupadd asmdba
# groupadd asmoper
为方便管理,建议为grid和db各自创建管理账号
# useradd -g oinstall -G asmdba,asmadmin,asmoper,dba grid -- 安装grid时,三个组可以分别选asmdba,asmoper,asmadmin
# useradd -g oinstall -G dba,oper,asmdba oracle
建目录,注意下权限:
# mkdir -p /u01/app/grid -- grid_base
# mkdir -p /u01/app/11.2.0/grid -- grid_home
# chown -R grid:oinstall /u01
# mkdir -p /u01/app/oracle -- oracle_base
# chown oracle:oinstall /u01/app/oracle
# chmod -R 775 /u01
另外,你这个问题,看看下面的目录的权限所有者:
$ls -ltr /tmp/CVU_11.2.0.3.0_grid
如果不是grid:dba 请修改为grid:dba即可。
数据库
2019-05-17 18:10:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
SQLite中的时间日期函数
这是我学习SQLite时做的笔记,参考并翻译了Chris Newman写的《SQLite》中的《Working with Dates and Times》一文中的部分内容。
SQLite包含了如下时间/日期函数:
datetime().......................产生日期和时间
date()...........................产生日期
time()...........................产生时间
strftime().......................对以上三个函数产生的日期和时间进行格式化
datetime()的用法是:datetime(日期/时间,修正符,修正符...)
date()和time()的语法与datetime()相同。
在时间/日期函数里可以使用如下格式的字符串作为参数:
YYYY-MM-DD
YYYY-MM-DD HH:MM
YYYY-MM-DD HH:MM:SS
YYYY-MM-DD HH:MM:SS.SSS
HH:MM
HH:MM:SS
HH:MM:SS.SSS
now
其中now是产生现在的时间。
举例(写这个笔记的时间是2006年10月17日晚8点到10点,测试环境:SQLite 2.8.17,WinXP,北京时间):
例1.
select datetime('now');
结果:2006-10-17 12:55:54
例2.
select datetime('2006-10-17');
结果:2006-10-17 12:00:00
例3.
select datetime('2006-10-17 00:20:00','+1 hour','-12 minute');
结果:2006-10-17 01:08:00
例4.
select date('2006-10-17','+1 day','+1 year');
结果:2007-10-18
例5.
select datetime('now','start of year');
结果:2006-01-01 00:00:00
例6.
select datetime('now','start of month');
结果:2006-10-01 00:00:00
例7.
select datetime('now','start of day');
结果:2006-10-17 00:00:00
例8.
select datetime('now','+10 hour','start of day','+10 hour');
结果:2006-10-17 10:00:00
例9.
select datetime('now','localtime');
结果:2006-10-17 21:21:47
例10.
select datetime('now','+8 hour');
结果:2006-10-17 21:24:45
例3中的+1 hour和-12 minute表示可以在基本时间上(datetime函数的第一个参数)增加或减少一定时间。
例5中的start of year表示一年开始的时间。
从例8可以看出,尽管第2个参数加上了10个小时,但是却被第3个参数“start of day”把时间归零到00:00:00,随后的第4个参数在00:00:00
的基础上把时间增加了10个小时变成了10:00:00。
例9把格林威治时区转换成本地时区。
例10把格林威治时区转换成东八区。
strftime()函数可以把YYYY-MM-DD HH:MM:SS格式的日期字符串转换成其它形式的字符串。
strftime()的语法是strftime(格式, 日期/时间, 修正符, 修正符, ...)
它可以用以下的符号对日期和时间进行格式化:
%d 月份, 01-31
%f 小数形式的秒,SS.SSS
%H 小时, 00-23
%j 算出某一天是该年的第几天,001-366
%m 月份,00-12
%M 分钟, 00-59
%s 从1970年1月1日到现在的秒数
%S 秒, 00-59
%w 星期, 0-6 (0是星期天)
%W 算出某一天属于该年的第几周, 01-53
%Y 年, YYYY
%% 百分号
strftime()的用法举例如下:
例11.
select strftime('%Y.%m.%d %H:%M:%S','now','localtime');
结果:2006.10.17 21:41:09
例11用圆点作为日期的分隔附,并把时间转换为当地的时区的时间。
-------------------
select datetime('2015-06-10 11:17:00','+1 day','-1 hour','-10 minute','+1 year','start of day','+1 hour');
注意前面的条件会被后面的覆盖.
sqlite> select strftime('%Y-%m-%d %H:%M:%S','now','localtime');
注意格式化时要使用指定的%符号,其实相当于c里面的sprintf
数据库
2019-05-17 17:21:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
一个很全的API链接文档
以下是使用Spring data Jpa操作ES的一些记录

在ElasticsearchRepository中我们可以使用 Not Add Like Or Between 等关键词自动创建查询语句。
记住上面这句话,代码示例: public interface EmployeeRepository extends ElasticsearchRepository { /** * 通过ID字段查询 */ Employee queryEmployeeById(String id); }

打开这个类我们发现: @NoRepositoryBean public interface ElasticsearchRepository extends ElasticsearchCrudRepository { S index(S var1); Iterable search(QueryBuilder var1); Page search(QueryBuilder var1, Pageable var2); Page search(SearchQuery var1); Page searchSimilar(T var1, String[] var2, Pageable var3); void refresh(); Class getEntityClass(); }

那么具体关键字有哪些呢?下面一一列出:
关键字 使用示例 等同于的ES查询
And findByNameAndPrice {“bool” : {“must” : [ {“field” : {“name” : “?”}}, {“field” : {“price” : “?”}} ]}}
Or findByNameOrPrice {“bool” : {“should” : [ {“field” : {“name” : “?”}}, {“field” : {“price” : “?”}} ]}}
Is findByName {“bool” : {“must” : {“field” : {“name” : “?”}}}}
Not findByNameNot {“bool” : {“must_not” : {“field” : {“name” : “?”}}}}
Between findByPriceBetween {“bool” : {“must” : {“range” : {“price” : {“from” : ?,”to” : ?,”include_lower” : true,”include_upper” : true}}}}}
LessThanEqual findByPriceLessThan {“bool” : {“must” : {“range” : {“price” : {“from” : null,”to” : ?,”include_lower” : true,”include_upper” : true}}}}}
GreaterThanEqual findByPriceGreaterThan {“bool” : {“must” : {“range” : {“price” : {“from” : ?,”to” : null,”include_lower” : true,”include_upper” : true}}}}}
Before findByPriceBefore {“bool” : {“must” : {“range” : {“price” : {“from” : null,”to” : ?,”include_lower” : true,”include_upper” : true}}}}}
After findByPriceAfter {“bool” : {“must” : {“range” : {“price” : {“from” : ?,”to” : null,”include_lower” : true,”include_upper” : true}}}}}
Like findByNameLike {“bool” : {“must” : {“field” : {“name” : {“query” : “? *”,”analyze_wildcard” : true}}}}}
StartingWith findByNameStartingWith {“bool” : {“must” : {“field” : {“name” : {“query” : “? *”,”analyze_wildcard” : true}}}}}
EndingWith findByNameEndingWith {“bool” : {“must” : {“field” : {“name” : {“query” : “*?”,”analyze_wildcard” : true}}}}}
Contains/Containing findByNameContaining {“bool” : {“must” : {“field” : {“name” : {“query” : “?”,”analyze_wildcard” : true}}}}}
In findByNameIn(Collectionnames) {“bool” : {“must” : {“bool” : {“should” : [ {“field” : {“name” : “?”}}, {“field” : {“name” : “?”}} ]}}}}
NotIn findByNameNotIn(Collectionnames) {“bool” : {“must_not” : {“bool” : {“should” : {“field” : {“name” : “?”}}}}}}
True findByAvailableTrue {“bool” : {“must” : {“field” : {“available” : true}}}}
False
OrderBy
findByAvailableFalse
findByAvailableTrueOrderByNameDesc
{“bool” : {“must” : {“field” : {“available” : false}}}}
{“sort” : [{ “name” : {“order” : “desc”} }],”bool” : {“must” : {“field” : {“available” : true}}}}
那么通过上述我们就可以写出一个简单的例子: @Autowired private EmployeeRepository employeeRepository; /** * 查询 */ @RequestMapping("/query/{id}") public Employee query(@PathVariable("id") String id) { Employee accountInfo = employeeRepository.queryEmployeeById(id); System.err.println(accountInfo.toString()); return accountInfo; } /** * 聚合查询测试 */ @RequestMapping("/querySum") public Iterable querySum() { /** * 创建查询体 */ BoolQueryBuilder builder = QueryBuilders.boolQuery(); /** * 设置聚合条件 */ RangeQueryBuilder query = QueryBuilders.rangeQuery("age").from("30").to("60"); /** * 将聚合条件设置入查询体之中 */ builder.must(query); Iterable search = employeeRepository.search(builder); return search; }

至此最基本的功能已经完成
思考:
为什么要使用ElasticsearchRepository而不使用原生的ES 的 SQL呢?

后记:感觉这样并不好用,建议看这篇博客 ESBboss
数据库
2019-05-17 16:52:00