Quantcast
Channel: CodeSection,代码区,数据库(综合) - CodeSec
Viewing all 6262 articles
Browse latest View live

Neo4j学习笔记十一【事物】

$
0
0

之前关于事物一章,由于当时的环境不方便测试所以跳过去了,现在回过头来,这一章一定要了解下,因为Neo4j是支持ACID的,示例项目采用上一章建的项目neo4j_sample下的springboot_sdn_embedded,使用Neo4j核心API演示。

事物声明方式

在没有引入Spring之前,事物采用如下原始的方式声明,引入Spring之后只需要@Transactional,这个相信大家都懂。

... try(Transaction tx = graphDB.beginTx()){ ... tx.success(); } ...

另外有一点要注意下,如果在Neo4j中做任意与模式相关的操作(创建模式索引),需要在一个单独的事物中,否则会抛出异常。

事物隔离级别

下面先代码测试下看看Neo4j默认的事物隔离级别是什么样的

#给john节点添加age属性 start john = node(143) set john.age = 30; //为了方便同时调试两个线程,项目引入spring-boot-starter-web,直接把父项目的spring-boot-starter改掉即可 @RestController publicclassTransactionController{ @Autowired privateTransactionService transactionService; @RequestMapping(path ="/threadA", method = RequestMethod.GET) publicStringtreadA(){ transactionService.threadA(); return"ok"; } @RequestMapping(path ="/threadB", method = RequestMethod.GET) publicStringtreadB(){ transactionService.threadB(); return"ok"; } } @Service publicclassTransactionService{ @Autowired privateGraphDatabaseService graphDatabaseService; @Transactional publicvoidthreadA(){ //1 Node john = graphDatabaseService.getNodeById(143l); System.out.println(john.getProperty("age")); //4 john = graphDatabaseService.getNodeById(143l); System.out.println(john.getProperty("age")); //6 john = graphDatabaseService.getNodeById(143l); System.out.println(john.getProperty("age")); } @Transactional publicvoidthreadB(){ //2 Node john = graphDatabaseService.getNodeById(143l); System.out.println(john.getProperty("age")); //3 john.setProperty("age",35); System.out.println(john.getProperty("age")); //5、threadB方法结束,提交事物 } } //主要测试代码如上,但是这样会有个问题,启动项目的时候会首先初始化Ne4jConfig中的GraphDatabaseService, //此时SessionFactory还没加载会得到一个空的driver,导致项目启动失败。通过如下办法可以解决, //即在graphDatabaseService()方法中主动调用getSessionFactory(),将SessionFactory先初始化好 @Bean publicGraphDatabaseServicegraphDatabaseService(){ getSessionFactory(); EmbeddedDriver embeddedDriver = (EmbeddedDriver) Components.driver(); returnembeddedDriver.getGraphDatabaseService(); } IDEA中同时调试两个线程

随便选择一个红色断点右击,会弹出一个对话框,选择将All改成Thread,并设置成默认,这样调试的时候,在Debugger标签页就能选择对应的线程debug。


Neo4j学习笔记十一【事物】

浏览器开两个窗口先后请求localhost:8080/threadA和localhost:8080/threadB,首先断点都停在了controller,然后按照顺序选择对应的线程debug。我debug的顺序在TransactionService注释中已经标明,输出结果依次为30、30、35、30、35,所以最终可以得出结论,threadA可以读到threadB已经提交过的修改,也就是说和传统关系型数据库的READ COMMITTED隔离级别相似。

更高级别的锁控制

Neo4j的事物是由清晰的读锁和写锁来控制每一个图形数据库资源的,下面我们看下如何手动控制锁

publicvoidreadLock(){ try(Transaction tx= graphDatabaseService.beginTx()){ //1 Node john = graphDatabaseService.getNodeById(143l); System.out.println(john.getProperty("age")); //读锁,其他线程对于该节点的写会等待读锁释放 tx.acquireReadLock(john); //4 john = graphDatabaseService.getNodeById(143l); System.out.println(john.getProperty("age")); tx.success(); } } @Transactional publicvoidwriteWaitReadLock(){ //2 Node john = graphDatabaseService.getNodeById(143l); System.out.println(john.getProperty("age")); //3 john.setProperty("age",38); System.out.println(john.getProperty("age")); } @RequestMapping(path ="/readLock", method = RequestMethod.GET) publicStringreadLock(){ transactionService.readLock(); return"ok"; } @RequestMapping(path ="/writeWaitReadLock", method = RequestMethod.GET) publicStringwriteWaitReadLock(){ transactionService.writeWaitReadLock(); return"ok"; }

跟之前一样的方式调试下,在readLock()方法中通过tx.acquireReadLock(john),获取了john节点的读锁,然后再跑writeWaitReadLock(),当跑到步骤3的setProperty方法时会进入等待,此时再跑完readLock()线程,事物提交了,读锁也自动释放了,writeWaitReadLock()线程会立刻被激活,然后顺利完成自己的事物。输出结果依次为35、35、35、38,正常。


What is a big innodb_log_file_size?

$
0
0

In this post, we’ll discuss what constitutes a big innodb_log_file_size , and how it can affect performance.

In the comments for our post on Percona Server 5.7 performance improvements , someone asked why we use innodb_log_file_size = 10G with an indication that it might be too big?

In my previous post ( https://www.percona.com/blog/2016/05/17/mysql-5-7-read-write-benchmarks/ ), the example used innodb_log_file_size = 15G .Is that too big? Let’s take a more detailed look at this.

First, let me start by rephrasing my warning: the log file size should be set as big as possible, but not bigger than necessary. A bigger log file size is betterfor performance, but it has a drawback (a significant one) that you need to worry about: the recovery time after a crash. You need to balance recovery time in the rare event of acrash recovery versus maximizing throughput during peak operations. This limitation can translate to a 20x longer crash recovery process!

But how big is “big enough”? Is it48MB (the default value), 1-2GB (which I often see in production), or 10-15GB (like we use for benchmarks)?

I wrote about how the innodb_log_file_size is related to background flushing five years ago, and I recommend this post if you are interested in details:

InnoDB Flushing: Theory and solutions

Since thattime many improvements have been made both in Percona Server and MySQL, but a small innodb_log_file_size still affects the throughput.

How? Let’s review how writes happen in InnoDB. Practically all data pagewrites happen in the background. It seems like background writes shouldn’t affect user query performance, but it does. The more intense background writes are, the more resources are taken away from the user foreground workload. There are three big forces that rule background writes:

How close checkpoint age is to theasync point (again, see previous material https://www.percona.com/blog/2011/04/04/innodb-flushing-theory-and-solutions/ ). This is adaptive flushing. How close is innodb_max_dirty_pages_pct to the percentage of actualdirty pages. You can see this in the LRU flushing metrics. What amount of free pages are defined by innodb_lru_scan_depth . This is also inLRU flushing metrics.

So in this equation innodb_log_file_size defines the async point, and how big checkpoint age can be.

To show a practical application of these forces, I’ve provided some chart data. I will use charts from the Percona Monitoring and Management tool and data from Percona Server 5.7.

Before jumping to graphs, let me remind you that the max checkpoint age is defined not only by innodb_log_file_size , but also innodb_log_files_in_group (which is usually “2” by default). So innodb_log_file_size = 2GB will have 4GB of log space, from which MySQL will use about 3.24GB (MySQL makes extra reservations to avoid a situation when we fully run out of log space).

Below are graphs from atpcc-mysql benchmark with 1500 warehouses, which provides about 150GB of data. I used innodb_buffer_pool_size = 64GB , and I made two runs:

with innodb_log_file_size = 2GB with innodb_log_file_size = 15GB

Other details about my setup:

CPU: 56 logical CPU threads servers Intel(R) Xeon(R) CPU E5-2683 v3 @ 2.00GHz OS: Ubuntu 16.04 Kernel 4.4.0-21-generic The storage device is Samsung SM863 SATA SSD, single device, with ext4 filesystem MySQL versions: Percona Server 5.7.11 innodb_io_capacity=5000 / innodb_io_capacity_max=7500

On the first chart, let’s look at the max checkpoint age, current checkpoint age and amount of flushed pages per second:


What is a big innodb_log_file_size?

. . . and also a related graph of how many pages are flushed by different forces (LRU flushing and adaptive flushing). You can receive this data by enabling innodb_monitor_enable = '%' .


What is a big innodb_log_file_size?

From these charts, we can see that with 2GB innodb_log_file_size InnoDB is forced by adaptive flushing to flush (write) more pages, because the current checkpoint age (uncheckpointed bytes) is very close to Max Checkpoint Age. To see the checkpoint age in MySQL, you can use the innodb_metrics table and metrics recovery_log_lsn_checkpoint_age and recovery_log_max_modified_age_sync .

In thecase using innodb_log_file_size = 15GB , the main flushing is done via LRU flushing (to keep 5000 pages ( innodb_lru_scan_depth ) free per buffer pool instance). From the first graph we can figure that uncheckpointed bytes never reach 12GB, so in this case using innodb_log_file_size = 15GB is overkill. We might be fine withinnodb_log_file_size=8GB but we wouldn’t know unless we set the innodb_log_file_size big enough. MySQL 5.7 comes with a very convenient improvement: now it is much easier to change the innodb_log_file_size , but it still requires aserver restart. I wish we could change it online, like we can for innodb_buffer_pool_size (I do not see technical barriers for this).

Let’s also look into theInnoDB buffer pool content:


What is a big innodb_log_file_size?

We can see that there are more modified pages in thecase with 15GB log files (which is good, as more modified pages means less work done in the background).

And the most interesting question: how does it affect throughput?


What is a big innodb_log_file_size?

With innodb_log_file_size = 2GB , the throughput is about 20% worse.With a 2GB log size, you can see that often zero transactions are processed within one second this is bad, and says that the flushing algorithm still needs improvements in cases when the checkpoint age is close to or at theasync point.

This should make a convincing case that using big

Peter Zaitsev: RocksDB 101

$
0
0

Peter Zaitsev: RocksDB 101
After we announced that Percona offers support for RocksDB, we sawmany people looking for more details about this storage engine. Here is a quick list of some of the most frequent questions we get.

Q: What is RocksDB?

A: Quoting the homepage of the project :

RocksDB is an embeddable persistent key-value store for fast storage. RocksDB can also be the foundation for a client-server database, but our current focus is on embedded workloads.

RocksDB builds on LevelDB to be scalable to run on servers with many CPU cores, to efficiently use fast storage, to support IO-bound, in-memory and write-once workloads, and to be flexible to allow for innovation.

Q: Where is it available?

A: You have 2 main options to get RocksDB:

Build it from source Use Percona Server for MongoDB which offers precompiled binaries

In both cases you will then need to start MongoDB with --storageEngine = rocksdb .

Q: What are the main features of RocksDB?

A: Because of its design using LSM trees, RocksDB offers excellent write performance without sacrificing too much read performance. And as a modern storage engine, it compresses data.

So each time you are concerned with MongoDB write performance, RocksDB is a good candidate.

Also note that RocksDB has been developed with fast storage in mind.

Q: Why is RocksDB write optimized?

A: RocksDB uses LSM trees to store data, unlike most other storage engines which are using B-Trees.

In most cases, B-Trees offer a very good tradeoff between read performance and write performance; this is why they are so widely used in the database world. However when the working set no longer fits in memory, writes become extremely slow because at least an I/O is needed for each write operation.

LSM trees are designed to amortize the cost of writes: data is written to log files that are sequentially written to disk and never modified. Then a background thread merges the log files (compaction). With this design a single I/O can flush to disk tens or hundreds of write operations.

The tradeoff is that reading a document is more complex and therefore slower than for a B-Tree; because we don’t know in advance in which log file the latest version of the data is stored, we may need to read multiple files to perform a single read. Tricks like bloom filters help alleviate this issue.

Q: How is RocksDB performance compared to other storage engine?

Mark Callaghan from Facebook published results for cached databases (data fits in memory) some time ago.

Vadim Tkachenko from Percona publishedadditional results when data is larger than memory.

Q: Where can I find RocksDB support?

A: You can report issues here , go to this Facebook group to discuss RocksDB-related topics, orhire us.

Q: How can I run backups?

Storage-engine agnostic methods like cold backups or volume snapshots work with RocksDB.

RocksDB also has native support for hot backups with the following command:

Shell

db.adminCommand({setParameter:1, rocksdbBackup: “/path/to/backup/dir”})

See this post from Facebook/Parse engineering team for more details.

The LSM tree design makes incremental backups much easier than with many technologies and rocks-strata is probably a good place to start.

Conclusion

The storage engine ecosystem for MongoDB is quickly advancingnow with at least 3 strong contenders: WiredTiger, RocksDB and PerconaFT. If you want to learn more from RocksDB, PerconaFT and Percona Server for MongoDB, please register for myfree webinar on Wed Oct 28 at 11am Pacific Time.

New in Cloudera Enterprise 5.8: SQL Editor and Other Productivity Improvements

$
0
0
Cloudera Enterprise 5.8 includes the latest release of Hue (3.10), the webUI that makes Apache Hadoop easier to use.

As part of Cloudera’s continuing investments in user experience and productivity, Cloudera Enterprise 5.8 includes a new release ofHue that makes several common tasks much easier. In the remainder of this post, we’ll provide a summary of the main improvements. (Hue 3.10 is also available for a quick try in one click on demo.gethue.com .)

New SQL Editor

Hue’s new code editor is a single-page app that is much simpler to use than the previous editor. (Although the editor currently focuses on SQL, support for more languages is possible in the future.) Here is a list of some of the new features:

Ability to switch between queries without any page reload Live history of running and past queries Query result grid is simplified and lets you refine your results Code editor has more operations like autocomplete values, search and replace, fold code, go to line number Ability to drag & drop saved queries into workflows (learn more )
New in Cloudera Enterprise 5.8: SQL Editor and Other Productivity Improvements

This video demo shows them in action:

Read more about the new SQL editor here .

New Home Page

Hue documents can now be managed via an intuitive directory and file-based interface. Rather than utilizing the tag-based system from older versions of Hue, you can create your own directories and subdirectories and drag and drop documents within the simple file browser interface. You can also import and export documents or directories directly from the home Page. Furthermore, easily share a folder or document with other users or groups by selecting the desired item(s) and selecting “Share” in the contextual menu or in the top-right icon menu.


New in Cloudera Enterprise 5.8: SQL Editor and Other Productivity Improvements

Read more about it here .

Cloudera Manager Database Wizard

In order to support the native load balancer for HA and improved performance (up to 10x), Hue needs to be configured with a robust RDBMSlike mysql, PostgreSQL, or Oracle Database. That setup can now be done directly from the Cloudera Manager interface, which will let you enter the properties and test the connection of the Hue service. Additional new Hue instances will automatically be configured for you.


New in Cloudera Enterprise 5.8: SQL Editor and Other Productivity Improvements
UI for Securing Solr Collections

The Apache Sentry app now let’s you edit Apache Solr collection privileges via a web UI, instead of a configuration file. (Apache Sentry allows you to define who can access or update Hive, Impala, or Solr data on a fine-grained/policy-based basis.) So, it is now much easier to control the authorization of all your Solr indexes and thus take advantage of Hue’s Dynamic Search dashboards .


New in Cloudera Enterprise 5.8: SQL Editor and Other Productivity Improvements

Read more about it here .

Idle Session Timeout

Administrators can now enforce and manage idle session timeouts in Hue. We’ve also improved the experience of re-authenticating into Hue when a user’s session is timed out by introducing a new login modal that prevents the user from losing current work.


New in Cloudera Enterprise 5.8: SQL Editor and Other Productivity Improvements

Read more about it here .

Next Up!

More SQL improvements and optimizations are in the pipeline, including new support for very large queries via SQL auto-complete, query browsing and export, and one-click auto-scheduling.

If you have any questions, feel free to comment here, on the hue-user list, or via @gethue !

OracleORA错误解决方案

$
0
0

今天在Debug的时候报错了如下信息:


OracleORA错误解决方案

后来综合了网上的东西,总结如下:

ORA-00001: 违反唯一约束条件 (.)

错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。

ORA-00017: 请求会话以设置跟踪事件

ORA-00018: 超出最大会话数

ORA-00019: 超出最大会话许可数

ORA-00020: 超出最大进程数 ()

ORA-00021: 会话附属于其它某些进程;无法转换会话

ORA-00022: 无效的会话 ID;访问被拒绝

ORA-00023: 会话引用进程私用内存;无法分离会话

ORA-00024: 单一进程模式下不允许从多个进程注册

ORA-00025: 无法分配

ORA-00026: 丢失或无效的会话 ID

ORA-00027: 无法删去当前会话

ORA-00028: 您的会话己被删去

ORA-00029: 会话不是用户会话

ORA-00030: 用户会话 ID 不存在。

ORA-00031: 标记要删去的会话

ORA-00032: 无效的会话移植口令

ORA-00033: 当前的会话具有空的移植口令

ORA-00034: 无法在当前 PL/SQL 会话中

ORA-00035: LICENSE_MAX_USERS 不能小于当前用户数

ORA-00036: 超过递归 SQL () 级的最大值

ORA-00037: 无法转换到属于不同服务器组的会话

ORA-00038: 无法创建会话: 服务器组属于其它用户

ORA-00050: 获取入队时操作系统出错

ORA-00051: 等待资源超时

说明:如果Oracle在等待资源时出现超时错误,会触发此异常。

ORA-00052: 超出最大入队资源数 ()

ORA-00053: 超出最大入队数

ORA-00054: 资源正忙,要求指定 NOWAIT

英文解析:resource busy and acquire with NOWAIT specified

错误解析:表被锁住了,要不等待表解锁,要不就去kill了它。

ORA-00055: 超出 DML 锁的最大数

ORA-00056: 对象 '.' 上的 DDL 锁以不兼容模式挂起

ORA-00057: 超出临时表锁的最大数

ORA-00058: DB_BLOCK_SIZE 必须为才可安装此数据库 (非 )

ORA-00059: 超出 DB_FILES 的最大值

ORA-00060: 等待资源时检测到死锁

说明:当产生死锁的时候,Oracle10g、11gOracle自动处理死锁。

ORA-00061: 另一个例程设置了不同的 DML_LOCKS,由于死锁使事务回退。

ORA-00062: 无法获得 DML 全表锁定;DML_LOCKS 为 0

ORA-00063: 超出 LOG_FILES 的最大数

ORA-00064: 对象过大以至无法分配在此 O/S (,)

ORA-00065: FIXED_DATE 的初始化失败

ORA-00066: LOG_FILES 为 但需要成为 才可兼容

ORA-00067: 值 对参数 无效;至少必须为

ORA-00068: 值 对参数 无效,必须在 和 之间

ORA-00069: 无法获得锁定 -- 禁用了表锁定

ORA-00070: 命令无效

ORA-00071: 进程号必须介于 1 和 之间

ORA-00072: 进程""不活动

ORA-00073: 命令 介于 和 个参数之间时使用

ORA-00074: 未指定进程

ORA-00075: 在此例程未找到进程 ""

ORA-00076: 未找到转储

ORA-00077: 转储 无效

ORA-00078: 无法按名称转储变量

ORA-00079: 未找到变量

ORA-00080: 层次 指定的全局区域无效

ORA-00081: 地址范围 [,) 不可读
ORA-00082: 的内存大小不在有效集合 [1], [2], [4] 之内

ORA-00083: 警告: 可能损坏映射的 SGA

ORA-00084: 全局区域必须为 PGA, SGA 或 UGA

ORA-00085: 当前调用不存在

ORA-00086: 用户调用不存在

ORA-00087: 命令无法在远程例程上执行

ORA-00088: 共享服务器无法执行命令

ORA-00089: ORADEBUG 命令中无效的例程号

ORA-00090: 未能将内存分配给群集数据库 ORADEBUG 命令

ORA-00091: LARGE_POOL_SIZE 至少必须为

ORA-00092: LARGE_POOL_SIZE 必须大于 LARGE_POOL_MIN_ALLOC

ORA-00093: 必须介于 和 之间

ORA-00094: 要求整数值

ORA-00096: 值 对参数 无效,它必须来自 之间

ORA-00097: 使用 Oracle SQL 特性不在 SQL92 级中

ORA-00099: 等待资源时发生超时,可能是 PDML 死锁所致

ORA-00100: 未找到数据

ORA-00101: 系统参数 DISPATCHERS 的说明无效

ORA-00102: 调度程序无法使用网络协议

ORA-00103: 无效的网络协议;供调度程序备用

ORA-00104: 检测到死锁;全部公用服务器已锁定等待资源

ORA-00105: 未配置网络协议 的调度机制

ORA-00106: 无法在连接到调度程序时启动/关闭数据库

ORA-00107: 无法连接到 ORACLE 监听器进程

ORA-00108: 无法设置调度程序以同步进行连接

ORA-00111: 由于服务器数目限制在 , 所以没有启动所有服务器

ORA-00112: 仅能创建多达 (最多指定) 个调度程序

ORA-00113: 协议名 过长

ORA-00114: 缺少系统参数 SERVICE_NAMES 的值

ORA-00115: 连接被拒绝;调度程序连接表已满

ORA-00116: SERVICE_NAMES 名过长

ORA-00117: 系统参数 SERVICE_NAMES 的值超出范围

ORA-00118: 系统参数 DISPATCHERS 的值超出范围

ORA-00119: 系统参数 的说明无效

ORA-00120: 未启用或安装调度机制

ORA-00121: 在缺少 DISPATCHERS 的情况下指定了 SHARED_SERVERS

ORA-00122: 无法初始化网络配置

ORA-00123: 空闲公用服务器终止

ORA-00124: 在缺少 MAX_SHARED_SERVERS 的情况下指定了 DISPATCHERS

ORA-00125: 连接被拒绝;无效的演示文稿

ORA-00126: 连接被拒绝;无效的重复

ORA-00127: 调度进程 不存在

ORA-00128: 此命令需要调度进程名

ORA-00129: 监听程序地址验证失败 ''

ORA-00130: 监听程序地址 '' 无效

ORA-00131: 网络协议不支持注册 ''

ORA-00132: 语法错误或无法解析的网络名称 ''

ORA-00150: 重复的事务处理 ID

ORA-00151: 无效的事务处理 ID

ORA-00152: 当前会话与请求的会话不匹配

ORA-00153: XA 库中的内部错误

ORA-00154: 事务处理监视器中的协议错误

ORA-00155: 无法在全局事务处理之外执行工作

ORA-00160: 全局事务处理长度 超出了最大值 ()

ORA-00161: 事务处理的分支长度 非法 (允许的最大长度为 )

ORA-00162: 外部 dbid 的长度 超出了最大值 ()

ORA-00163: 内部数据库名长度 超出了最大值 ()

ORA-00164: 在分布式事务处理中不允许独立的事务处理

ORA-00165: 不允许对远程操作进行可移植分布式自治转换

ORA-00200: 无法创建控制文件

ORA-00201: 控制文件版本 与 ORACLE 版本 不兼容

ORA-00202: 控制文件: ''

ORA-00203: 使用错误的控制文件

ORA-00204: 读控制文件时出错 (块 ,# 块 )

ORA-00205: 标识控制文件出错,有关详情,请检查警告日志

ORA-00206: 写控制文件时出错 (块 ,# 块 )

ORA-00207: 控制文件不能用于同一数据库

ORA-00208: 控制文件的名称数超出限制

ORA-00209: 控制文件块大小不匹配,有关详情,请检查警告日志

ORA-00210: 无法打开指定的控制文件

ORA-00211: 控制文件与先前的控制文件不匹配

ORA-00212: 块大小 低于要求的最小大小 ( 字节)

ORA-00213: 不能重新使用控制文件;原文件大小为 ,还需

ORA-00214: 控制文件 '' 版本 与文件 '' 版本 不一致

ORA-00215: 必须至少存在一个控制文件

ORA-00216: 无法重新调整从 8.0.2 移植的控制文件大小

ORA-00217: 从 9.0.1 进行移植无法重新调整控制文件的大小

ORA-00218: 控制文件的块大小 与 DB_BLOCK_SIZE () 不匹配

ORA-00219: 要求的控制文件大小 超出了允许的最大值

ORA-00220: 第一个例程未安装控制文件,有关详情,请检查警告日志

ORA-00221: 写入控制文件出错

ORA-00222: 操作将重新使用当前已安装控制文件的名称

ORA-00223: 转换文件无效或版本不正确

ORA-00224: 控制文件重设大小尝试使用非法记录类型 ()

ORA-00225: 控制文件的预期大小 与实际大小 不同

ORA-00226: 备用控制文件打开时不允许进行操作

ORA-00227: 控制文件中检测到损坏的块: (块 ,# 块 )

ORA-00228: 备用控制文件名长度超出了最大长度

ORA-00229: 操作不允许: 已挂起快照控制文件入队

ORA-00230: 操作不允许: 无法使用快照控制文件入队

ORA-00231: 快照控制文件未命名

ORA-00232: 快照控制文件不存在, 已损坏或无法读取

ORA-00233: 控制文件副本已损坏或无法读取

ORA-00234: 标识或打开快照或复制控制文件时出错

ORA-00235: 控制文件固定表因并发更新而不一致

ORA-00236: 快照操作不允许: 挂上的控制文件为备份文件

ORA-00237: 快照操作不允许: 控制文件新近创建

ORA-00238: 操作将重用属于数据库一部分的文件名

ORA-00250: 未启动存档器

ORA-00251: LOG_ARCHIVE_DUPLEX_DEST 不能是与字符串 相同的目的地

ORA-00252: 日志 在线程 上为空,无法存档

ORA-00253: 字符限制在 以内,归档目的字符串 超出此限制

ORA-00254: 存档控制字符串 '' 时出错

ORA-00255: 存档日志 (线程 , 序列 # ) 时出错

ORA-00256: 无法翻译归档目的字符串

ORA-00257: 存档器错误。在释放之前仅限于内部连接

ORA-00258: NOARCHIVELOG 模式下的人工存档必须标识日志

ORA-00259: 日志 (打开线程 ) 为当前日志,无法存档

ORA-00260: 无法找到联机日志序列 (线程 )

ORA-00261: 正在存档或修改日志 (线程 )

ORA-00262: 当前日志 (关闭线程 ) 无法切换

ORA-00263: 线程 没有需要存档的记录

ORA-00264: 不要求恢复

ORA-00265: 要求例程恢复,无法设置 ARCHIVELOG 模式

ORA-00266: 需要存档日志文件名

ORA-00267: 无需存档日志文件名

ORA-00268: 指定的日志文件不存在 ''

ORA-00269: 指定的日志文件为线程 的一部分 (非 )

ORA-00270: 创建存档日志 时出错

ORA-00271: 没有需要存档的日志

ORA-00272: 写存档日志 时出错

ORA-00273: 未记录的直接加载数据的介质恢复

ORA-00274: 非法恢复选项

ORA-00275: 已经开始介质恢复

ORA-00276: CHANGE 关键字已指定但未给出更改编号

ORA-00277: UNTIL 恢复标志 的非法选项

ORA-00278: 此恢复不再需要日志文件 ''

ORA-00279: 更改 (在 生成) 对于线程 是必需的

ORA-00280: 更改 对于线程 是按序列 # 进行的

ORA-00281: 不能使用调度进程执行介质恢复

ORA-00282: UPI 调用不被支持,请使用 ALTER DATABASE RECOVER

ORA-00283: 恢复会话因错误而取消

ORA-00284: 恢复会话仍在进行

ORA-00285: TIME 未作为字符串常数给出

ORA-00286: 无可用成员,或成员无有效数据

ORA-00287: 未找到指定的更改编号 (在线程 中)

ORA-00288: 要继续恢复,请键入 ALTER DATABASE RECOVER CONTINUE

ORA-00289: 建议:

ORA-00290: 操作系统出现存档错误。请参阅下面的错误

ORA-00291: PARALLEL 选项要求数字值

ORA-00292: 未安装并行恢复功能

ORA-00293: 控制文件与重做日志不同步

ORA-00294: 无效的存档日志格式标识 ''

ORA-00295: 数据文件号 无效,必须介于 1 与 之间

ORA-00296: 已超出 RECOVER DATAFILE LIST 的最大文件数 ()

ORA-00297: 必须在 RECOVER DATAFILE START 之前指定 RECOVER DATAFILE LIST

ORA-00298: 丢失或无效的 TIMEOUT 间隔

ORA-00299: 必须在数据文件 上使用文件级介质恢复

ORA-00300: 指定的重做日志块大小 非法 - 超出限制

ORA-00301: 添加日志文件 '' 时出错 - 无法创建文件

ORA-00302: 日志超出限制

ORA-00303: 无法处理多次中断的重做

ORA-00304: 请求的 INSTANCE_NUMBER 在使用中

ORA-00305: 日志 (线程 ) 不一致;属于另一个数据库

ORA-00306: 此数据库中的例程限制

ORA-00307: 请求的 INSTANCE_NUMBER 超出限制,最大为

ORA-00308: 无法打开存档日志 ''

ORA-00309: 日志属于错误的数据库

ORA-00310: 存档日志包含序列 ;要求序列

ORA-00311: 无法从存档日志读取标题

ORA-00312: 联机日志 线程 : ''

ORA-00313: 无法打开日志组 (线程 ) 的成员

ORA-00314: 日志 (线程 ),预计序号 与 不匹配

ORA-00315: 日志 (线程 ),标题中的线程 # 错误

ORA-00316: 日志 (线程 ),标题中的类型 不是日志文件

ORA-00317: 标题中的文件类型 不是日志文件

ORA-00318: 日志 (线程 ),预计文件大小 与 不匹配

ORA-00319: 日志 (线程 ) 具有错误的日志重置状态

ORA-00320: 无法从日志 (线程 ) 读取文件标题

ORA-00321: 日志 (线程 ),无法更新日志文件标题

ORA-00322: 日志 (线程 ) 不是当前副本

ORA-00323: 线程 的当前日志不可用而所有其它日志均需要存档

ORA-00324: 日志文件 '' 的翻译名 '' 太长, 字符超出 限制

ORA-00325: 已归档线程 的日志,标题中的线程 # 错误

ORA-00326: 日志在更改 开始,需要更早的更改

ORA-00327: 日志 (线程 ),实际大小 小于需要的

ORA-00328: 归档日志在更改 结束,需要稍后的更改

ORA-00329: 归档日志在更改 开始,需要更改

ORA-00330: 归档日志在更改 结束,需要更改

ORA-00331: 日志版本 与 ORACLE 版本 不兼容

ORA-00332: 归档日志过小 - 可能未完全归档

ORA-00333: 重做日志读取块 计数 出错

ORA-00334: 归档日志: ''

ORA-00335: 联机日志 : 没有此编号的日志,日志不存在

ORA-00336: 大小为 的日志文件块数小于最小 块数

ORA-00337: 日志文件 '' 不存在且未指定大小

ORA-00338: 日志 (线程 ) 比控制文件更新

ORA-00339: 归档日志未包含任何重做

ORA-00340: 处理联机日志 (线程 ) 时出现 I/O 错误

ORA-00341: 日志 (线程 ),标题中的日志 # 错误

ORA-00342: 归档日志在上一个 RESETLOGS 之前创建程序包

ORA-00343: 错误过多,已关闭日志成员

ORA-00344: 无法重新创建联机日志 ''

ORA-00345: 重做日志写入块 计数 出错

ORA-00346: 日志成员标记为 STALE

ORA-00347: 日志 (线程 ),预计块大小 与 不匹配

ORA-00348: 单一进程重做失败;必须中止例程

ORA-00349: 无法获得 '' 的块大小

ORA-00350: 日志 (线程 ) 中需要归档

ORA-00351: recover-to 时间无效

ORA-00352: 线程 的所有日志均需要归档 - 无法启用

ORA-00353: 日志损坏接近块 更改 时间

ORA-00354: 损坏重做日志块标题

ORA-00355: 更改编号无次序

ORA-00356: 更改说明中的长度不一致

ORA-00357: 日志文件指定了过多成员,最大为

ORA-00358: 指定了过多文件成员,最大为

ORA-00359: 日志文件组 不存在

ORA-00360: 非日志文件成员:

ORA-00361: 无法删除最后一个日志成员 (组 )

ORA-00362: 组成组 中的有效日志文件要求输入成员

ORA-00363: 日志不是归档版本

ORA-00364: 无法将标题写入新日志成员

ORA-00365: 指定日志不是正确的下一个日志

ORA-00366: 日志 (线程 ),文件标题中的校验和错误

ORA-00367: 日志文件标题中的校验和错误

ORA-00368: 重做日志块中的校验和错误

ORA-00369: 线程 的当前日志不可用且其它日志已被清除

ORA-00370: Rcbchange 操作过程中可能出现死锁

ORA-00371: 共享池内存不足

ORA-00372: 此时无法修改文件

ORA-00373: 联机日志版本 与 ORACLE 版本 不兼容

ORA-00374: 参数 db_block_size = 无效; 它必须是 的倍数, 范围为 [..]

ORA-00375: 无法获得默认 db_block_size

ORA-00376: 此时无法读取文件

ORA-00377: 文件 的频繁备份导致写操作延迟

ORA-00378: 无法按指定创建缓冲池

ORA-00379: 缓冲池 中无法提供 K 块大小的空闲缓冲区

ORA-00380: 无法指定 db_k_cache_size, 因为 K 是标准块大小

ORA-00381: 无法将新参数和旧参数同时用于缓冲区高速缓存的大小说明

ORA-00382: 不是有效的块大小, 有效范围为 [..]

ORA-00383: DEFAULT 高速缓存的块大小 不能减少至零

ORA-00384: 没有足够的内存来增加高速缓存的大小

ORA-00385: cannot enable Very Large Memory with new buffer cache parameters

ORA-00390: 日志 (线程 ) 正被清除,无法成为当前日志

ORA-00391: 所有线程必须同时转换为新的日志格式

ORA-00392: 日志 (线程 ) 正被清除,不允许操作

ORA-00393: 脱机数据文件的恢复需要日志 (线程 )

ORA-00394: 在尝试存档时重新使用联机日志

ORA-00395: '克隆' 数据库的联机日志必须重命名

ORA-00396: 错误 需要退回到单次遍历恢复

ORA-00397: 对于文件 (块 ), 检测到写入丢失情况

ORA-00398: 由于重新配置而中止了线程恢复

ORA-00399: 重做日志中的更改说明已损坏

ORA-00400: 无效的版本值 (对于参数 )

ORA-00401: 此版本不支持参数 的值

ORA-00402: 版本 的数据库更改无法用于版本

ORA-00403: () 不同于其它例程 ()

ORA-00404: 未找到转换文件: ''

ORA-00405: 兼容类型""

ORA-00406: COMPATIBLE 参数需要为 或更大

ORA-00407: 不允许从版本 . 到 . 滚动升级

ORA-00408: 参数 设置为 TRUE

ORA-00409: COMPATIBLE 必须是 或更高值才能使用 AUTO SEGMENT SPACE MANAGEMENT

ORA-00436: 没有 ORACLE 软件使用权,请与 Oracle 公司联系获得帮助

ORA-00437: 没有 ORACLE 软件功能使用权,请与 Oracle 公司联系获得帮助

ORA-00438: 未安装 选项

ORA-00439: 未启用特性:

ORA-00443: 背景进程 "" 未启动

ORA-00444: 背景进程 "" 启动时失败

ORA-00445: 背景进程 "" 在 秒之后仍没有启动

ORA-00446: 背景进程意外启动

ORA-00447: 背景进程出现致命错误

ORA-00448: 背景进程正常结束

ORA-00449: 背景进程 '' 因错误 异常终止

ORA-00470: LGWR 进程因错误而终止

ORA-00471: DBWR 进程因错误而终止

ORA-00472: PMON 进程因错误而终止

ORA-00473: ARCH 进程因错误而终止

ORA-00474: SMON 进程因错误而终止

ORA-00475: TRWR 进程因错误而终止

ORA-00476: RECO 进程因错误而终止

ORA-00477: SNP* 进程因错误而终止

ORA-00478: SMON 进程由于 错误终止

ORA-00480: LCK* 进程因错误而终止

ORA-00481: LMON 进程因错误而终止

ORA-00482: LMD* 进程因错误而终止

ORA-00483: 关闭进程过程中异常终止

ORA-00484: LMS* 进程因错误而终止

ORA-00485: DIAG 进程由于 错误终止

ORA-00486: 功能不可用

ORA-00568: 超出中断处理程序的最大数

ORA-00574: osndnt: $CANCEL 失败 (中断)

ORA-00575: osndnt: $QIO 失败 (发送 out-of-band 中断)

ORA-00576: 带内中断协议错误

ORA-00577: 带外中断协议错误

ORA-00578: 重置协议错误

ORA-00579: osndnt: 服务器收到连接请求格式不正确

ORA-00580: 协议版本不匹配

ORA-00581: osndnt: 无法分配上下文区域

ORA-00582: osndnt: 无法撤消分配上下文区域

ORA-00583: osndnt: $TRNLOG 失败

ORA-00584: 无法关闭连接

ORA-00585: 主机名称格式错误

ORA-00586: osndnt: LIB$ASN_WTH_MBX 失败

ORA-00587: 无法连接到远程主机

ORA-00588: 来自主机的信息过短

ORA-00589: 来自主机的信息数据长度错误

ORA-00590: 来自主机的信息类型错误

ORA-00591: 写入的字节数错误

ORA-00592: osndnt: $QIO 失败 (邮箱队列)

ORA-00593: osndnt: $DASSGN 失败 (网络设备)

ORA-00594: osndnt: $DASSGN 失败 (邮箱)

ORA-00595: osndnt: $QIO 失败 (接收)

ORA-00596: osndnt: $QIO 失败 (发送)

ORA-00597: osndnt: $QIO 失败 (邮箱队列)

ORA-00598: osndnt: $QIO IO 失败 (邮箱读取)

ORA-00600: 内部错误代码,参数: [], [], [], [], [], [], [], []

ORA-00601: 清除锁定冲突

ORA-00602: 内部编程异常错误

ORA-00603: ORACLE 服务器会话因致命错误而终止

ORA-00604: 递归 SQL 层 出现错误(error occurred at recursive SQL level 1)

ORA-00606: 内部错误代码

ORA-00607: 当更改数据块时出现内部错误

ORA-00701: 无法改变热启动数据库所需的对象

ORA-00702: 引导程序版本 '' 与版本 '' 不一致

ORA-00703: 超出行高速缓存例程锁的最大数

ORA-00704: 引导程序进程失败

ORA-00705: 启动过程中的状态不一致;请在关闭例程后重新启动

ORA-00706: 更改文件 '' 的格式时出错

ORA-00816: 错误信息无法转换

ORA-00900: 无效 SQL 语句

ORA-00901: 无效 CREATE 命令

ORA-00902: 无效数据类型

ORA-00903: 表名无效

英文解析:invalid table name

错误解析:例如动态SQL用绑定变量不能传参做表名,如果传参做表名就会触发这个错误

代码案例:declare

vc_sql varchar2(100);

vc_tablename varchar2(100):='dual';

begin

vc_sql:='insert into temp_phone2(phone)

select 55 from :1';

execute IMMEDIATE vc_sql using vc_tablename;

commit;

end;

ORA-00904: 无效的标识符

ORA-00905: 缺少关键字

ORA-00906: 缺少左括号

ORA-00907: 缺少右括号

ORA-00908: 缺少 NULL 关键字

ORA-00909: 参数个数无效

ORA-00910: 指定的长度对于数据类型而言过长

ORA-00911: 无效字符

ORA-00913: 值过多

ORA-00914: 缺少 ADD 关键字

ORA-00915: 当前不允许网络访问字典表

ORA-00917: 缺少逗号

ORA-00918: 未明确定义列

ORA-00919: 无效函数

ORA-00920: 无效的关系运算符

ORA-00921: 未预期的 SQL 命令结尾

ORA-00922: 缺少或无效选项

ORA-00923: 未找到预期 FROM 关键字

ORA-00924: 缺少 BY 关键字

ORA-00925: 缺失 INTO 关键字

ORA-00926: 缺少 VALUES 关键字

ORA-00927: 缺少等号

ORA-00928: 缺少 SELECT 关键字

ORA-00929: 缺少句号

ORA-00930: 缺少星号

ORA-00931: 缺少标识

ORA-00932: 不一致的数据类型: 要求 得到的却是

ORA-00933: SQL 命令未正确结束

ORA-00934: 此处不允许使用分组函数

ORA-00935: 分组函数的嵌套太深

ORA-00936: 缺少表达式

ORA-00937: 非单组分组函数

ORA-00938: 函数没有足够的参数

ORA-00939: 函数的参数过多

ORA-00940: 无效的 ALTER 命令

ORA-00941: 群集名缺少

ORA-00942: 表或视图不存在

ORA-00943: 群集不存在

ORA-00944: 没有足够的聚簇列数

ORA-00945: 指定的聚簇列不存在

ORA-00946: 缺少 TO 关键字

ORA-00947: 没有足够的值

ORA-00948: 不再支持 ALTER CLUSTER 语句

ORA-00949: 非法引用远程数据库

ORA-00950: 无效 DROP 选项

ORA-00951: 群集非空

ORA-00952: 缺少 GROUP 关键字

ORA-00953: 缺少或无效索引名

ORA-00954: 缺少 IDENTIFIED 关键字

ORA-00955: 名称已由现有对象使用

ORA-00956: 缺少或无效审计选项

ORA-00957: 列名重复

ORA-00958: 缺少 CHECK 关键字

ORA-00959: 表空间''不存在

ORA-00960: 选择列表中的命名含糊

ORA-00961: 错误的日期/间隔值

ORA-00962: group-by / order-by 表达式过多

ORA-00963: 不支持的间隔类型

ORA-00964: 表名不在 FROM 列表中

ORA-00965: 列别名中不允许'*'

ORA-00966: 缺少 TABLE 关键字

ORA-00967: 缺少 WHERE 关键字

ORA-00968: 缺少 INDEX 关键字

ORA-00969: 缺少 ON 关键字

ORA-00970: 缺少 WITH 关键字

ORA-00971: 缺少 SET 关键字

ORA-00972: 标识过长

错误说明:Oracle规定名称最长30个字符,超过长度就会报这个错误。

ORA-00973: 无效的行数估计

ORA-00974: 无效 PCTFREE 值 (百分比)

ORA-00975: 不允许日期 + 日期

ORA-00976: 此处不允许为 LEVEL, PRIOR 或 ROWNUM

ORA-00977: 重复的审计选项

ORA-00978: 嵌套分组函数没有 GROUT BY

ORA-00979: 不是 GROUP BY 表达式

ORA-00980: 同义词转换不再有效

说明:同义词创建时,不会去检测内容的准确性,即如果表不存在,也可以创建该表的同义词,但是select时会报ORA-00980

ORA-00981: 不能将表和系统审计选项混在一起

ORA-00982: 缺少加号

ORA-00984: 列在此处不允许

说明:创建CREATE TABLE ord_items(ord_no NUMBER(4)DEFAULT comment_id_seq.NEXTVAL NOT NULL)时报错

解决:序列值不能当做字段的默认值。

ORA-00985: 无效的程序名

ORA-00986: 缺少或无效组名

ORA-00987: 缺少或无效用户名

ORA-00988: 缺少或无效口令

ORA-00989: 给出的用户名口令过多

ORA-00990: 缺少或无效权限

说明:例如GRANT ALTER TABLE TO drm_mdm;这样赋权限就会报错,因为没有alter table的系统权限,只有alter any table

ORA-00991: 过程仅有 MAC 权限

ORA-00992: REVOKE 命令格式无效

ORA-00993: 缺少 GRANT 关键字

ORA-00994: 缺少 OPTION 关键字

ORA-00995: 缺少或无效同义词标识

ORA-00996: 连接运算符是 || 而不是 |

ORA-00997: 非法使用 LONG 数据类型

ORA-00998: 必须使用列别名命名此表达式

ORA-00999: 无效的视图名

ORA-01000: 超出打开游标的最大数

ORA-01001: 无效的游标

说明:当试图在不合法的游标上执行操作时,会触发此异常。例如从未打开的游标提取数据或关闭未打开的游标。

ORA-01002: 读取违反顺序

ORA-01003: 语句未进行语法分析

ORA-01004: 不支持默认用户名特性;登录被拒绝

ORA-01005: 未给出口令;登录被拒绝

ORA-01006: 赋值变量不存在

ORA-01007: 选择列表中没有变量

ORA-01008: 并非所有变量都已关联

ORA-01009: 缺少法定参数

ORA-01010: 无效的 OCI 操作

ORA-01011: 在与第 6 版服务器会话时不能使用第 7 版兼容模式

ORA-01012: 没有登录,没有连接到Oracle

说明:如果在没有连接到数据库的情况下,执行PL/SQL块,会触发此异常。

ORA-01013: 用户请求取消当前的操作

说明:一个可能是用户取消了操作;一个可能是超时。

ORA-01014: ORACLE 正在关闭过程中

ORA-01015: 循环登录请求

ORA-01016: 此函数仅可以在读取后调用

ORA-01017: 无效的用户名/口令;拒绝登录

英文解析:invalid username/password; logon denied

错误原因:账号密码错误

ORA-01018: 列不具有 LONG 数据类型

ORA-01019: 无法在用户方分配内存

ORA-01020: 未知的上下文状态

ORA-01021: 指定的上下文大小无效

ORA-01022: 此配置中不支持数据库操作

ORA-01023: 未找到游标上下文 (无效的游标编号)

ORA-01024: OCI 调用中的数据类型无效

ORA-01025: UPI 参数超出范围

ORA-01026: 赋值列表中存在多个大小 > 4000 的缓冲区

ORA-01027: 在数据定义操作中不允许对变量赋值

英文解析:bind variables not allowed for data definition operations

错误原因:在数据定义操作语句(create,alter,drop,rename,truncate)中使用了捆绑变量

ORA-01028: 内部双工错误

ORA-01029: 内部双工错误

ORA-01030: SELECT ...INTO 变量不存在

ORA-01031: 权限不足

说明:用户不足有操作此语句的权限

ORA-01032: 没有这样的用户标识

ORA-01033: ORACLE 正在初始化或关闭过程中

ORA-01034: ORACLE 不可用

ORA-01035: ORACLE 只允许具有 RESTRICTED SESSION 权限的用户使用

ORA-01036: 非法的变量名/编号

ORA-01037: 超出最大游标内存

ORA-01038: 无法写入数据库文件版本 (使用 ORACLE 版本 )

ORA-01039: 视图基本对象的权限不足

ORA-01040: 口令中的字符无效;登录被拒绝

ORA-01041: 内部错误,hostdef 扩展名不存在

说明:SQLPLUS修改了做了操作后,启动数据库报此错误,关闭SQLPLUS,重新打开一个就行

ORA-01042: 不允许使用打开游标分离会话

ORA-01043: 用户方内存损坏 [], [], [], []

ORA-01044: 缓冲区大小 (与变量关联) 超出了最大限制

ORA-01045: 用户 没有 CREATE SESSION 权限;登录被拒绝

ORA-01046: 无法获得扩展上下文区域的空间

ORA-01047: 以上错误出现在 schema=, package=, procedure= 中

ORA-01048: 给定的上下文中无法找到指定的过程

ORA-01049: 流动 RPC 中不支持按名称赋值

ORA-01050: 无法获得打开上下文区域的空间

ORA-01051: 延迟 rpc 缓冲区格式无效

ORA-01052: 未指定所需的目的 LOG_ARCHIVE_DUPLEX_DEST

ORA-01053: 无法读取用户存储地址

ORA-01054: 无法写入用户存储地址

ORA-01057: 用户出口中引用的 block.field 无效或有歧义

ORA-01058: 内部 New Upi 接口错误

ORA-01059: 在赋值或执行之前进行语法分析

ORA-01060: 不允许数组赋值或执行

ORA-01061: 无法使用第 7 版客户应用程序启动第 8 版服务器

ORA-01062: 无法分配定义缓冲区所需的内存

ORA-01070: 服务器使用 Oracle 的旧版本

ORA-01071: 无法不启动 ORACLE 而执行操作

ORA-01072: 无法停止 ORACLE;因为 ORACLE 不在运行

ORA-01073: 致命的连接错误: 不能识别的调用类型

ORA-01074: 无法关闭 ORACLE;请首先在注册会话中注销

ORA-01075: 您现在已登录

ORA-01076: 尚不支持每个进程的多次登录

ORA-01077: 背景进程初始化失败

ORA-01078: 处理系统参数失败

ORA-01079: ORALCE 数据库未正确创建,操作中止

ORA-01080: 关闭 ORACLE 时出错

ORA-01081: 无法启动已在运行的 ORACLE --- 请首先关闭

ORA-01082: 'row_locking = always' 要求事务处理处理选项

ORA-01083: 参数 "" 的值与其它例程序的相应参数值不一致。

ORA-01084: OCI 调用中的参数无效

ORA-01085: 延迟 rpc 到 ".." 之前的错误

ORA-01086: 从未创建保留点 ''

ORA-01087: 不能启动 ORALCE --- 现在已登录

ORA-01088: 不能在存在活动进程时关闭 ORACLE

ORA-01089: 正在进行紧急关闭 - 不允许进行任何操作

ORA-01090: 正在进行关闭 --- 不允许连接

ORA-01091: 强行启动出错

ORA-01092: ORACLE 例程终止。强行断开连接

ORA-01093: ALTER DATABASE CLOSE 仅允许在没有连接会话时使用

ORA-01094: ALTER DATABASE CLOSE 正在进行。不允许连接

ORA-01095: DML 语句处理了零个行

ORA-01096: 程序版本 () 与例程 () 不兼容

ORA-01097: 无法在事务处理过程中关闭 - 首先提交或返回

ORA-01098: 在 Long Insert 过程中出现程序接口错误

ORA-01099: 如果在单进程模式下启动,则无法在 SHARED 模式下安装数据库

ORA-01100: 数据库已安装

ORA-01101: 要创建的数据库当前正由其它例程安装

ORA-01102: 无法在 EXCLUSIVE 模式下安装数据库

ORA-01103: 控制文件中的数据库名 '' 不是 ''

ORA-01104: 控制文件数 () 不等于

ORA-01105: 安装与其它例程的安装不兼容

ORA-01106: 必须在卸下之前关闭数据库

ORA-01107: 必须安装数据库才可以进行介质恢复

ORA-01108: 文件 正处于备份或介质恢复过程中

ORA-01109: 数据库未打开

ORA-01110: 数据文件 : ''

ORA-01111: 数据文件 名称未知 - 请重命名以更正文件

ORA-01112: 未启动介质恢复

ORA-01113: 文件 需要介质恢复

ORA-01114: 将块写入文件 时出现 IO 错误 (块 # )

ORA-01115: 从文件 读取块时出现 IO 错误 (块 # )

ORA-01116: 打开数据库文件时出错

ORA-01117: 对文件 '' 添加非法块大小: ;限制为

ORA-01118: 无法添加任何其它数据库文件: 超出限制

ORA-01119: 创建数据库文件 '' 时出错

ORA-01120: 无法删除联机数据库文件

ORA-01121: 无法重命名数据库文件 - 文件在使用中或在恢复中

ORA-01122: 数据库文件 验证失败

ORA-01123: 无法启动联机备份;未启用介质恢复

ORA-01124: 无法恢复数据文件 - 文件在使用中或在恢复中

ORA-01125: 无法禁用介质恢复 - 文件 设置了联机备份

ORA-01126: 对于此操作,数据库必须以 EXCLUSIVE 模式安装且未打开

ORA-01127: 数据库名 '' 超出 个字符的限制

ORA-01128: 无法启动联机备份 - 文件 处于脱机状态

ORA-01129: 用户默认或临时表空间不存在

ORA-01130: 数据库文件版本 与 ORACLE 版本 不兼容

ORA-01131: DB_FILES 系统参数值 超出限制

ORA-01132: 数据库文件名 '' 的长度超出 个字符的限制

ORA-01133: 日志文件名 '' 的长度超出 个字符的限制

ORA-01134: 数据库已由其它例程独立安装

ORA-01135: DML/query 访问的文件 处于脱机状态

ORA-01136: 文件 ( 块) 的指定大小小于 块的原大小

ORA-01137: 数据文件 仍处于脱机过程中

ORA-01138: 数据库必须在此例程中打开或根本没有打开

ORA-01139: RESETLOGS 选项仅在不完全数据库恢复后有效

ORA-01140: 无法结束联机备份 - 所有文件均处于脱机状态

ORA-01141: 重命名数据文件 时出错 - 未找到新文件 ''

ORA-01142: 无法结束联机备份 - 没有文件在备份中

ORA-01143: 不能禁用介质恢复 - 文件 需要介质恢复

ORA-01144: 文件大小 ( 块) 超出 块的最大数

ORA-01145: 除非启用了介质恢复,否则不允许紧急脱机

ORA-01146: 无法启动联机备份 - 文件 已在备份中

ORA-01147: SYSTEM 表空间文件 处于脱机状态

ORA-01149: 无法关闭 - 文件 设置了联机备份

ORA-01150: 无法防止写入 - 文件 设置了联机备份

ORA-01151: 如果需要,请使用介质恢复以恢复块和恢复备份

ORA-01152: 文件 没有从完备的旧备份中恢复

ORA-01153: 激活了不兼容的介质恢复

ORA-01154: 数据库正在运行。现在不允许打开, 关闭, 安装和拆卸

ORA-01155: 正在打开, 关闭, 安装或拆卸数据库

ORA-01156: 进行中的恢复可能需要访问文件

ORA-01157: 无法标识/锁定数据文件 - 请参阅 DBWR 跟踪文件

ORA-01158: 数据库 已安装

ORA-01159: 文件并非来自先前文件的同一数据库 - 数据库标识错误

ORA-01160: 文件不是

ORA-01161: 文件标题中的数据库名 与给定的名称 不匹配

ORA-01162: 文件标题中的块大小 与配置的块大小不匹配

ORA-01163: SIZE 子句表示 (块),但应与标题 匹配

ORA-01164: MAXLOGFILES 不可以超出

ORA-01165: MAXDATAFILES 不可以超出

ORA-01166: 文件数量 大于 ()

ORA-01167: 这两个文件为相同的文件/组号或相同的文件

ORA-01168: 物理块大小 与其它成员的大小 不匹配

ORA-01169: 未找到 DATAFILE 编号 1。此编号必须存在

ORA-01170: 文件未找到 ''

ORA-01171: 数据文件因高级检查点错误而将脱机

ORA-01172: 线程的恢复停止在块(在文件中)

ORA-01173: 数据字典指明从系统表空间丢失的数据文件

ORA-01174: DB_FILES 为 ,但需要为 才能兼容

ORA-01175: 例程允许数据字典具有多于个文件

ORA-01176: 控制文件允许数据字典具有多于个文件

ORA-01177: 数据文件与字典不匹配- 可能是旧的原型

ORA-01178: 文件 在最后一个 CREATE CONTROLFILE 之前创建,无法重新创建

ORA-01179: 文件 不存在

ORA-01180: 无法创建数据文件 1

ORA-01181: 文件在最后一个 RESETLOGS 之前创建,无法重新创建

ORA-01182: 无法创建数据文件 - 文件在使用中或在恢复中

ORA-01183: 无法在 SHARED 模式下安装数据库

ORA-01184: 日志文件组已经存在

ORA-01185: 日志文件组号无效

ORA-01186: 文件 验证测试失败

ORA-01187: 由于验证测试失败而无法从文件 读取

ORA-01188: 标题中的块大小与物理块大小不匹配

ORA-01189: 文件来自于与先前文件不同的 RESETLOGS

ORA-01190: 控制文件或数据文件来自于最后一个 RESETLOGS 之前

ORA-01191: 文件已经脱机 - 无法进行正常脱机

ORA-01192: 必须启用至少一个线程

ORA-01193: 文件与恢复开始时的文件不同

ORA-01194: 文件需要更多的恢复来保持一致性

ORA-01195: 文件的联机备份需要更多的恢复来保持一致性

ORA-01196: 文件由于介质恢复会话失败而不一致

ORA-01197: 线程仅包含一个日志

ORA-01198: 在选项为 RESETLOGS 时必须指定日志文件的大小

ORA-01199: 文件不处于联机备份模式

ORA-01200: 的实际文件大小小于块的正确大小

ORA-01201: 文件标题无法正确写入

ORA-01202: 此文件的原型错误 - 创建时间错误

ORA-01203: 此文件的原型错误 - 创建 SCN 错误

ORA-01204: 文件号是而不是 - 文件错误

ORA-01205: 不是数据文件 - 标题的类型编号是

ORA-01206: 文件不是此数据库的一部份 - 数据库标识错误

ORA-01207: 文件比控制文件更新 - 旧的控制文件

ORA-01208: 数据文件是旧的版本 - 不能访问当前版本

ORA-01209: 数据文件来自最后一个 RESETLOGS 之前

ORA-01210: 数据文件标题是介质损坏

ORA-01211: Oracle7 数据文件不是来自于 Oracle8 的移植版本

ORA-01212: MAXLOGMEMBERS 不可以超出

ORA-01213: MAXINSTANCES 不可以超出

ORA-01214: MAXLOGHISTORY 不可以超出

ORA-01215: 启用的线程在 CREATE CONTROLFILE 之后丢失

ORA-01216: 线程预计在 CREATE CONTROLFILE 之后禁用

ORA-01217: 日志文件成员属于一个不同的日志文件组

ORA-01218: 日志文件成员来自于不同的时间点

ORA-01219: 数据库未打开: 仅允许在固定表/视图中查询

ORA-01220: 在数据库打开之前基于文件的分类非法

ORA-01221: 数据文件与背景进程的文件不同

ORA-01222: 的 MAXINSTANCES 要求 MAXLOGFILES 至少是而不是

ORA-01223: 必须指定 RESETLOGS 以设置新的数据库名

ORA-01224: 标题中的组号与 GROUP 不匹配

ORA-01225: 线程编号大于 MAXINSTANCES

ORA-01226: 日志成员的文件标题与其它成员不一致

ORA-01227: 日志与其它日志不一致

ORA-01228: SET DATABASE 选项要求安装源数据库

ORA-01229: 数据文件与日志不一致

ORA-01230: 无法设置只读 - 文件处于脱机状态

ORA-01231: 无法设置读写 - 文件处于脱机状态

ORA-01232: 无法启动联机备份 - 文件是只读文件

ORA-01233: 文件是只读文件 - 无法使用备份控制文件恢复

ORA-01234: 无法终止文件的备份 - 文件在使用或在恢复中

ORA-01235: END BACKUP 对文件失败而对成功

ORA-01236: 文件标题访问的初始化过程中出现错误

ORA-01237: 无法扩展数据文件

ORA-01238: 无法收缩数据文件

ORA-01239: 数据库必须在 ARCHIVELOG 模式下使用外部高速缓存

ORA-01240: 一个命令中添加的数据文件过多

ORA-01241: 外部高速缓存已停止

ORA-01242: 数据文件出现介质错误: 数据库处于 NOARCHIVELOG 模式

ORA-01243: 系统表空间文件出现介质错误

ORA-01244: 未命名的数据文件由介质恢复添加至控制文件

ORA-01245: RESETLOGS 完成时脱机文件将丢失

ORA-01246: 通过表空间的 TSPITR 来恢复文件

ORA-01247: 通过表空间的 TSPITR 来恢复数据库

ORA-01248: 文件在将来的不完整恢复中创建

ORA-01249: 不允许在 '克隆' 数据库中存档

ORA-01250: 文件标题访问的终止过程中出现错误

ORA-01251: 文件号的未知文件标题版本读取

ORA-01252: 无法禁止写 - 文件在恢复管理器备份中

ORA-01253: 无法启动联机备份 - 文件在恢复管理器备份中

ORA-01254: 无法结束联机备份 - 文件在恢复管理器备份中

ORA-01255: 无法关闭 - 文件在恢复管理器备份中

ORA-01256: 在锁定数据库文件 时出错

ORA-01257: 不能重用数据库文件 ,文件大小未知

ORA-01258: 无法删除临时文件

ORA-01259: 无法删除数据文件

ORA-01260: 当数据库打开时, 不能发出 ALTER DATABASE END BACKUP 命令

ORA-01261: 无法转换参数 目标字符串

ORA-01262: 在文件目标目录上无法进行统计

ORA-01263: 文件目标目录的名称无效

ORA-01264: 无法创建 文件名

ORA-01265: 无法删除文件

ORA-01266: 无法创建唯一的文件名

ORA-01267: 无法获取日期/时间

ORA-01268: 用于变更永久性 TABLESPACE 的 TEMPFILE 子句无效

ORA-01269: 目标参数字符串过长

ORA-01270: STANDBY_PRESERVES_NAMES 为 true 时, 不允许进行 操作

ORA-01271: 无法创建文件 的新文件名

ORA-01272: 只有当提供文件名时, 才允许 REUSE。

ORA-01274: 无法添加数据文件 '' - 无法创建文件

ORA-01275: 自动进行备用文件管理时, 不允许进行 操作。

ORA-01276: 无法添加文件 。 相应文件具有一个 Oracle 管理文件文件名。

ORA-01277: 文件 '' 已存在

ORA-01278: 创建文件 '' 出错

ORA-01279: db_files 太大

ORA-01280: 严重的 LogMiner 错误。

ORA-01281: 指定的 SCN 范围无效

ORA-01282: 指定的日期范围无效

ORA-01283: 指定选项无效

ORA-01284: 文件 无法打开

ORA-01285: 读取文件 时出错

ORA-01286: 由于 DB_ID 不匹配无法添加文件

ORA-01287: 文件 来源于其他的数据库原型

ORA-01288: 文件 来自不同的数据库实体

ORA-01289: 无法添加重复的日志文件

ORA-01290: 无法删除未列出的日志文件

ORA-01291: 丢失的日志文件

ORA-01292: 当前 LogMiner 会话无指定的日志文件

ORA-01293: 时间或 SCN 范围没有完全包含在列出的日志文件中

ORA-01294: 当处理字典文件 中的信息时出错,可能损坏

ORA-01295: 字典 和日志文件之间的 DB_ID 不匹配

ORA-01296: 字典 和日志文件之间的字符集不匹配

ORA-01297: 字典 和日志文件之间的重做版本不匹配

ORA-01298: 字典 和最早的日志文件不是 SCN 可兼容的

ORA-01299: 字典 对应于不同的数据库原型

ORA-01300: 字典 和最早的日志文件之间已启用的线程位向量不匹配

ORA-01301: dbms_logmnr.USE_COLMAP 只用于有效字典

ORA-01302: 在 logmnr.opt 文件中出现语法错误

ORA-01303: 在 logmnr.opt 文件中指定的方案 不存在

ORA-01304: 在 logmnr.opt 文件中指定的表 , 方案 不存在

ORA-01305: 在 logmnr.opt 文件中指定的列 不存在于表 ,, 方案 中

ORA-01306: 在从 v$logmnr_contents 中选择之前必须调用 dbms_logmnr.start_logmnr()

ORA-01307: 当前无活动的 LogMiner 会话

ORA-01308: 未设置初始化参数 utl_file_dir

ORA-01309: 会话无效

ORA-01310: lcr_mine 函数不支持请求的返回类型

ORA-01311: mine_value 函数的调用非法

ORA-01312: 指定的表/列不存在

ORA-01313: LogMiner 字典列类型不同于指定的类型

ORA-01314: 要挖掘的列名字面上应是字符串

ORA-01315: 日志文件在选取过程中已被添加或移去

ORA-01316: 已连接到 Logminer 会话中

ORA-01317: 未连接到 Logminer 会话中

ORA-01318: Logminer 会话未启动

ORA-01319: Logminer 会话属性无效

ORA-01320: Logminer 字典属性无效

ORA-01321: SCN 范围没有完全包含在所列日志文件中

ORA-01322: 这样的表不存在

ORA-01323: 状态无效

ORA-01324: 由于 DB_ID 匹配出错, 无法添加文件

ORA-01325: 要构建日志流, 必须启用“归档日志”模式

ORA-01326: 要构建日志流, 兼容性必须大于等于 8.2

ORA-01327: 无法按构建的要求锁定系统字典 (锁为排他锁)

ORA-01328: 一次只能进行一个构建操作

ORA-01329: 无法截断所需的构建表

ORA-01330: 加载所需的构建表时出现问题

ORA-01331: 运行构建时出现一般错误

ORA-01332: Logminer 字典内部错误

ORA-01333: 无法构建 Logminer 字典

ORA-01334: logminer 字典进程上下文无效或缺失

ORA-01335: 此功能尚未实现

ORA-01336: 无法打开指定的字典文件

ORA-01337: 日志文件的兼容版本不同

ORA-01338: 其他进程已附加到 LogMiner 会话

ORA-01339: 日志文件过旧

ORA-01340: NLS error

ORA-01341: LogMiner 内存不足

ORA-01342: LogMiner 由于无法暂存检查点数据而无法恢复会话

ORA-01343: LogMiner - 遇到崩溃的重做块

ORA-01344: LogMiner 协调器已挂接

ORA-01345: 必须启用补充日志数据以纳入到日志流中

ORA-01346: 从属 LogMiner 会话依赖于存在补充性的记录数据

ORA-01347: 未找到补充日志数据

ORA-01348: LogMiner 测试事件

ORA-01349: LogMiner 跟踪事件

ORA-01350: 必须指定表空间名

ORA-01351: 为 Logminer 字典提供的表空间不存在

ORA-01352: 为 Logminer 溢出提供的表空间不存在

ORA-01353: 正在退出 Logminer 会话

ORA-01370: 指定的重启 SCN 太旧

ORA-01371: 未找到完整的 LogMiner 目录

ORA-01372: 用于指定 LogMiner 操作的进程数不足

ORA-01373: insufficient memory for staging persistent LogMiner session

ORA-01374: log_parallelism greater than 1 not supported in this release

ORA-01400: 无法将 NULL 插入 ()

ORA-01401: 插入的值对于列过大

ORA-01402: 视图 WITH CHECK OPTIDN 违反 where 子句

ORA-01403: 未找到数据

说明:SELECT INTO没有返回一行,或视图引用一个没有被赋值的plsql表单元素

ORA-01404: ALTER COLUMN 将使索引过大

ORA-01405: 读取的列值为 NULL

ORA-01406: 读取的列值被截断

ORA-01407: 无法更新 () 为 NULL

ORA-01408: 此列列表已编制索引

ORA-01409: 不可以使用 NOSORT 选项;行不是按升序排列

ORA-01410: 无效的 ROWID

说明:当将字符转变为ROWID时,如果使用了无效的字符串,会触发此异常。

ORA-01411: 无法在指示器中存储列长度

ORA-01412: 此数据类型不允许零长度

ORA-01413: 压缩十进制数字缓冲区中的非法值

ORA-01414: 尝试对数组赋值时的无效数组长度

ORA-01415: 太多不同的聚组函数

ORA-01416: 两表无法彼此外部连接

ORA-01417: 表可以外部连接到至多一个其它的表

ORA-01418: 指定的索引不存在

ORA-01419: datdts: 非法的格式代码

ORA-01420: datstd: 非法的格式代码

ORA-01421: datrnd/dattrn: 非法的精确度规定

ORA-01422: 实际返回的行数超出请求的行数

说明:SELECT INTO 返回多行

ORA-01423: 检查实际读取的多余行时出错

ORA-01424: 换码符之后缺少或非法字符

ORA-01425: 换码符必须是长度为 1 的字符串

ORA-01426: 数字溢出

ORA-01427: 单行子查询返回多于一个行

ORA-01428: 参数''超出范围

ORA-01429: 索引组织表: 没有存储溢出行段的数据段

ORA-01430: 表中已经存在要添加的列

ORA-01431: GRANT 命令中的内部不一致

ORA-01432: 要删除的公用同义词不存在

ORA-01433: 要创建的同义词已经定义

ORA-01434: 要删除的隐含同义词不存在

ORA-01435: 用户不存在

ORA-01436: 用户数据中的 CONNECT BY 循环

ORA-01437: 无法连接 CONNECT BY

ORA-01438: 值大于此列指定的允许精确度

ORA-01439: 要更改数据类型,则要修改的列必须为空 (empty)

错误解析:ORACLE不允许表字段在存在数据的情况下,直接MODIFY“更改”数据类型,当直接修改数据类型的时候就会报这样的错误

代码案例:当使用MODIFY直接修改表字段从varchar2改为number的时候,就会报错

参考解决方案:这里要把number类型的CITY_ID字段改为varchar2

ALTER TABLE business_hall_info ADD CITY_ID_temp varchar2(32);

UPDATE business_hall_info SET CITY_ID_temp = CITY_ID;

UPDATE business_hall_info SET CITY_ID = NULL;

ALTER TABLE BUSINESS_HALL_INFO MODIFY CITY_ID varchar2(32);

UPDATE business_hall_info SET CITY_ID = CITY_ID_temp;

ALTER TABLE business_hall_info DROP COLUMN CITY_ID_temp; --结束

注意:同数据类型间,修改精度,例如varchar100 改为 varchar102 可以直接修改; 但把精度改小,如果不小于存储数据的实际长度,也允许修改,如果小于实际长度,则报其他错误,例如 ORA-01441 。

ORA-01440: 要减小精确度或标度,则要修改的列必须为空 (empty)

ORA-01441: 无法减小列长度, 因为一些值过大

英文解析:cannot decrease column length because some value is too big

错误解析:当你MODIFY修改一个字段的数据类型精度比实际存储的数据小时,就会报这个错误!例如把VARCHAR2(100)改为VARCHAR2(1)(原字段里存储有数据并且长度大于1)

ORA-01442: 要修改为 NOT NULL 的列已经是 NOT NULL

ORA-01443: 内部不一致;结果视图列中的数据类型非法

ORA-01444: 内部不一致;内部数据类型映射为无效外部类型

ORA-01445: 无法从没有键值保存表的连接视图中选择 ROWID

ORA-01446: 无法从含 DISTINCT, GROUP BY 等子句的视图中选择 ROWID

ORA-01447: ALTER TABLE 语句无法用于聚簇列

ORA-01448: 在更改要求的类型之前必须删除索引

ORA-01449: 列包含 NULL 值;无法将其改变为 NOT NULL

ORA-01450: 超出最大的关键字长度 ()

ORA-01451: 要修改为 NULL 的列无法修改为 NULL

说明:主键不能为空,当你置主键为空的时候会报此错误。

ORA-01452: 无法 CREATE UNIQUE INDEX;找到重复的关键字

ORA-01453: SET TRANSACTION 必须是事务处理的第一个语句

ORA-01454: 无法将列转换为数值数据类型

ORA-01455: 转换列溢出整数数据类型

ORA-01456: 不可以在 READ ONLY 事务处理中执行插入/删除/更新操作

ORA-01457: 转换列溢出十进制数据类型

ORA-01458: 内部变量字符串长度非法

ORA-01459: 变量字符串长度非法

ORA-01460: 转换请求无法实现或不合理

ORA-01461: 仅可以为插入 LONG 列的 LONG 值赋值

ORA-01462: 不能插入超出 4000 个字符的文字型字符串

ORA-01463: 不能使用当前约束条件修改列数据类型

ORA-01464: 表或视图的循环授权(授予原始授权者)

ORA-01465: 无效的十六进制数字

ORA-01466: 无法读数据 - 表定义已更改

ORA-01467: 分类 (sort) 关键字过长

ORA-01468: 一个谓词只能引用一个外部连接表

ORA-01469: PRIOR 后面只能跟列名

ORA-01470: In-list 迭代不支持混合运算符

ORA-01471: 无法创建与对象同名的同义词

ORA-01472: 无法将 CONNECT BY 用于 DISTINCT,GROUP BY 等的视图

ORA-01473: CONNECT BY 子句中不能具有子查询

ORA-01474: START WITH 或 PRIOR 不能没有 CONNECT BY

ORA-01475: 必须对游标重新进行语法分析以更改赋值变量的数据类型

ORA-01476: 除数为 0

错误说明:当分母为0的时候会报这个错误,用case when对分母进行判断可以正常select,但INSET还是会报错,解决方法是建函数fun_percent,通过调用函数解决这个问题。

ORA-01477: 用户数据区域描述符过大

ORA-01478: 数组赋值不可以包括任何 LONG 列

ORA-01479: 缓冲区中的最后一个字符不是 Null

ORA-01480: STR 赋值变量缺少空后缀

ORA-01481: 无效的数字格式模型

ORA-01482: 不受支持的字符集

ORA-01483: DATE 或 NUMBER 赋值变量的长度无效

ORA-01484: 数组仅可以与 PL/SQL 语句关联

ORA-01485: 编译赋值长度不同于执行赋值长度

ORA-01486: 数组元素的大小过大

ORA-01487: 给定缓冲区的压缩十进制数字过大

ORA-01488: 输入数据中的无效半字节或字节

ORA-01489: 字符串连接的结果过长

说明:对varchar2的字段截取,再||接字符串,如果超过4000,则报此错误,SUBSTR是截取字符个数。

ORA-01490: 无效的 ANALYZE 命令

ORA-01491: CASCADE 选项无效

ORA-01492: LIST 选项无效

ORA-01493: 指定的 SAMPLE 大小无效

ORA-01494: 指定的 SIZE 无效

ORA-01495: 未找到指定的链接行表

ORA-01496: 指定的链接行表不正确

ORA-01497: 非法的 ANALYZE CLUSTER 选项

ORA-01498: 块检查失败 - 请参阅跟踪文件

ORA-01499: 表/索引交叉引用失败 - 请参阅跟踪文件

ORA-01500: 无法获得日期/时间

ORA-01501: CREATE DATABASE 失败

ORA-01502: 索引'.'或这类索引的分区处于不可用状态

ORA-01503: CREATE CONTROLFILE 失败

ORA-01504: 数据库名''与参数 db_name ''不匹配

ORA-01505: 添加日志文件时出错

ORA-01506: 缺少或非法数据库名

ORA-01507: 未安装数据库

ORA-01508: 无法创建数据库;文件''的行出错

ORA-01509: 指定的名称''与实际名称''不匹配

ORA-01510: 删除日志文件时出错

ORA-01511: 重命名日志/数据文件时出错

ORA-01512: 重命名日志文件时出错 - 未找到新文件

ORA-01513: 操作系统返回无效的当前时间

ORA-01514: 日志说明中出现错误: 没有此类日志

ORA-01515: 删除日志组时出错: 没有此类日志

ORA-01516: 不存在的日志文件, 数据文件或临时文件 ''

ORA-01517: 日志成员: ''

ORA-01518: CREATE DATABASE 必须指定多于一个日志文件

ORA-01519: 在处理文件''的邻近行时出错

ORA-01520: 要添加的数据文件数 () 超出限制

ORA-01521: 添加数据文件时出错

ORA-01522: 要重命名的文件''不存在

ORA-01523: 无法将数据文件重命名为'' - 文件已是数据库的一部分

ORA-01524: 无法将数据文件创建为'' - 文件已是数据库的一部分

ORA-01525: 重命名数据文件时出错

ORA-01526: 打开文件''时出错

ORA-01527: 读文件出错

ORA-01528: 处理 SQL 语句时出现 EOF

ORA-01529: 关闭文件''时出错

ORA-01530: 例程已安装数据库

ORA-01531: 例程已打开数据库

ORA-01532: 无法创建数据库;例程在他处启动

ORA-01533: 无法重命名文件'';文件不属于表空间

ORA-01534: 回退段''不存在

ORA-01535: 回退段''已经存在

ORA-01536: 超出表空间''的空间限量

ORA-01537: 无法添加数据文件'' - 文件已是数据库的一部分

ORA-01538: 无法获得任何回退段

ORA-01539: 表空间''未联机

ORA-01540: 表空间''未脱机

ORA-01541: 系统表空间无法脱机;如有必要请关闭

ORA-01542: 表空间''脱机,无法在其中分配空间

ORA-01543: 表空间 '' 已经存在

ORA-01544: 无法删除系统回退段

ORA-01545: 指定的回退段''不可用

ORA-01546: 表空间包含活动回退段''

ORA-01547: 警告: RECOVER 成功但 OPEN RESETLOGS 将出现如下错误

ORA-01548: 已找到活动回退段'',终止删除表空间

ORA-01549: 表空间非空,请使用 INCLUDING CONTENTS 选项

ORA-01550: 无法删除系统表空间

ORA-01551: 扩展回退段,释放用的块

ORA-01552: 非系统表空间''无法使用系统回退段

ORA-01553: MAXEXTENTS 不得小于当前分配的区

ORA-01554: 超出事务处理表的事务处理空间

ORA-01555: 快照过旧: 回退段号 在名称为 "" 过小

说明:UNDO表空间不足导致的错误。

ORA-01556: 回退段的 MINEXTENTS 必须大于 1

ORA-01557: 回退段的区必须至少为块

ORA-01558: 超出回退段中的事务处理标识(号)

ORA-01559: 回退段的 MAXEXTENTS 值必须大于 1

ORA-01560: LIKE 样式包含的字符不完整或非法

ORA-01561: 无法删除指定表空间中的所有对象

ORA-01562: 扩展回退段号失败

ORA-01563: 回退段是 PUBLIC,需要使用 PUBLIC 关键字

ORA-01564: 回退段不是 PUBLIC

ORA-01565: 标识文件''时出错

ORA-01566: 文件在 DROP LOGFILE 中被指定了多次

ORA-01567: 删除日志时将在线索中保留少于两个日志文件

ORA-01568: 无法在 PUBLIC 设置空间限量

ORA-01569: 对于系统字典表来说,数据文件过小

ORA-01570: MINEXTENTS 不得大于当前分配的区

ORA-01571: 重做版本与 ORACLE 版本不兼容

ORA-01572: 回退段 '' 无法联机, 区已超出

ORA-01573: 正在关闭例程,不允许继续更改

ORA-01574: 超出并发事务处理的最大数

ORA-01575: 等待空间管理资源超时

ORA-01576: 例程锁定协议版本与 ORACLE 版本不兼容

ORA-01577: 无法添加日志文件'' - 文件已是数据库的一部分

ORA-01578: ORACLE 数据块损坏(文件号,块号)

ORA-01579: 恢复过程中出现写错误

ORA-01580: 创建控制备份文件时出错

ORA-01581: 尝试使用已分配的回退段 () 新区 ()

ORA-01582: 无法打开要备份的控制文件

ORA-01583: 无法获得要备份的控制文件的块大小

ORA-01584: 无法获得要备份的控制文件的文件大小

ORA-01585: 标识备份文件时出错

ORA-01586: 无法打开要备份的目标文件

ORA-01587: 复制控制文件的备份文件时出错

ORA-01588: 要打开数据库则必须使用 RESETLOGS 选项

ORA-01589: 要打开数据库则必须使用 RESETLOGS 或 NORESETLOGS 选项

ORA-01590: 段可用列表数 () 超出最大数

ORA-01591: 锁定已被有问题的分配事务处理挂起

ORA-01592: 将第 7 版回退段 () 转换为 Oracle 8 版格式时出错

ORA-01593: 回退段最佳大小 ( blks) 小于计算的初始大小 ( blks)

ORA-01594: 尝试放回已释放的回退段 () 区 ()

ORA-01595: 释放区 () 回退段 () 时出错

ORA-01596: 无法在参数中指定系统

ORA-01597: 无法改变联机或脱机系统回退段

ORA-01598: 回退段''未联机

ORA-01599: 无法获得回退段 (), 高速缓存空间已满

ORA-01600: 至多只有一个""在子句""()中

ORA-01601: 子句""()中的存储桶大小非法

ORA-01603: 子句""()中的分组大小非法

ORA-01604: 子句""()中的编号范围非法

ORA-01605: 子句""()中缺少编号

ORA-01606: gc_files_to_locks 不同于另一已安装例程的参数

ORA-01608: 无法将回退段''联机,其状态为 ()

ORA-01609: 日志是线程的当前日志 - 无法删除成员

ORA-01610: 使用 BACKUP CONTROLFILE 选项的恢复必须已完成

ORA-01611: 线程编号无效 - 必须介于 1 和之间

ORA-01612: 线程已经启用

ORA-01613: 线程只有日志 - 要求至少启用 2 个日志

ORA-01614: 线程正忙 - 无法启用

ORA-01615: 线程已安装 - 无法禁用

ORA-01616: 线程已打开 - 无法禁用

ORA-01617: 无法安装: 不是有效的线程编号

ORA-01618: 线程未启用 - 无法安装

ORA-01619: 线程已由另一例程安装

ORA-01620: 没有可用于安装的公用线程

ORA-01621: 数据库打开时无法重命名当前日志的成员

ORA-01622: 必须指定线程编号 - 没有特定默认值

ORA-01623: 日志是线程的当前日志 - 无法删除

ORA-01624: 线程的紧急恢复需要日志

ORA-01625: 回退段''不属于此例程

ORA-01626: 回退段号''无法处理更多事务处理

ORA-01627: 回退段号''未联机

ORA-01628: 已达到 max # extents ()(回退段)

ORA-01629: 已达到 max # extents (),此时正在保存表空间的撤消

ORA-01630: 表空间中的 temp 段达到 max # extents()

ORA-01631: 表.达到 max # extents ()

ORA-01632: 索引.达到 max # extents ()

ORA-01633: 此操作需要 Real Application Clusters 选件

ORA-01634: 回退段号''即将脱机

ORA-01635: 指定的回退段编号 '' 不可用

ORA-01636: 回退段''已联机

ORA-01637: 回退段''正被另一例程 (#) 使用

ORA-01638: 参数 不允许 ORACLE 版本 装载群集数据库

ORA-01640: 无法将活动事务处理的表空间设置为只读

ORA-01641: 表空间''未联机- 无法添加数据文件

ORA-01642: 只读表空间''无需开始备份

ORA-01643: 系统表空间无法设置为只读

ORA-01644: 表空间''已经是只读

ORA-01645: 上次尝试设置读写已完成一半

ORA-01646: 表空间''不是只读 - 无法设置为读写

ORA-01647: 表空间''是只读,无法在其中分配空间

ORA-01648: 日志是禁用线程的当前日志

ORA-01649: 不允许进行备份控制文件操作

ORA-01650: 回退段无法通过(在表空间中)扩展

说明:表空间满引起的错误。

ORA-01651: 无法通过(在表空间中)扩展保存撤消段

说明:表空间满引起的错误。

ORA-01652: 无法通过(在表空间中)扩展 temp 段

说明:表空间满引起的错误。

ORA-01653: 表.无法通过(在表空间中)扩展

说明:表空间满引起的错误。

ORA-01654: 索引.无法通过(在表空间中)扩展

说明:表空间满引起的错误。

ORA-01655: 群集 . 无法通过 (在表空间 中) 扩展

说明:表空间满引起的错误。

ORA-01656: 最大区数 () 已在群集 . 中达到

ORA-01657: 无效的 SHRINK 选项值

ORA-01658: 无法为表空间?中的段?创建 INITIAL 区

说明:表空间满引起的错误。

ORA-01659: 无法分配超出的 MINEXTENTS(在表空间中)

ORA-01660: 表空间''已是永久性

ORA-01661: 表空间''已是临时性

ORA-01662: 表空间''非空且无法设置为暂时性

ORA-01663: 表空间''的内容不断变动

ORA-01664: 扩展排序段的事务处理已终止

ORA-01665: 控制文件不是一个备用控制文件

ORA-01666: 控制文件用于备用数据库

ORA-01667: 无法添加任何其它表空间: 超出限制

ORA-01668: 对于数据文件的脱机,备用数据库要求使用 DROP 选项

ORA-01669: 备用数据库控制文件不一致

ORA-01670: 备用数据库恢复需要新数据文件

ORA-01671: 控制文件是备份文件,无法设置备用控制文件

ORA-01672: 控制文件可能缺少文件或具有额外文件

ORA-01673: 未标识数据文件

ORA-01674: 数据文件是一个旧的原型而非当前文件

ORA-01675: max_commit_propagation_delay 与其它例程不一致

ORA-01676: ''的备用文件名转换超出的最大长度

ORA-01677: 备用文件名转换参数不同于其它例程

ORA-01678: 参数 必须是一对样式字符串和取代字符串

ORA-01679: 数据库必须以 EXCLUSIVE 安装且未打开以激活

ORA-01680: 无法通过(在表空间中)扩展 LOB 段

ORA-01681: max # extents () 已在表空间中的 LOB 段达到

ORA-01682: 只读 DB 无法在表空间中分配临时空间

ORA-01683: 索引.分区无法通过(在表空间中)扩展

ORA-01684: max # extents () 已在表.分区中达到

ORA-01685: max # extents () 已在索引.分区中达到

ORA-01686: max # files () 对于表空间已达到

ORA-01687: 表空间''的指定记录属性与现有属性相同

ORA-01688: 表.分区无法通过(在表空间中)扩展

ORA-01689: 子句""()中出现语法错误

ORA-01690: 排序区太小

ORA-01691: Lob 段.无法通过(在表空间中)扩展

ORA-01692: Lob 段.分区无法通过(在表空间中)扩展

ORA-01693: max # extents () 已在 lob 段.中达到

ORA-01694: max # extents () 已在 lob 段.分区中达到

ORA-01695: 将回退段转换为版本 8.0.2 时出错

ORA-01696: 控制文件不是 '克隆' 控制文件

ORA-01697: 控制文件用于 '克隆' 数据库

ORA-01698: '克隆' 数据库仅可以具有 SYSTEM 联机回退段

ORA-01699: 正在导入表空间''以用于时间点恢复

ORA-01700: 列表中的用户名重复

ORA-01701: 此处不允许有群集

ORA-01702: 此处不允许有视图

ORA-01703: 缺少 SYNONYM 关键字

ORA-01704: 文字字符串过长

ORA-01705: 无法在关联列中指定外部连接

ORA-01706: 用户函数的结果值过大

ORA-01707: 缺少 LIST 关键字

ORA-01708: 需要 ACCESS 或 SESSION

ORA-01709: 程序不存在

ORA-01710: 缺少 OF 关键字

ORA-01711: 列出的权限重复

ORA-01712: 您不能授予不具有的权限

ORA-01713: 该权限的 GRANT OPTION 不存在

ORA-01714: 执行用户函数时出错

ORA-01715: UNIQUE 不可以与簇索引一起使用

ORA-01716: NOSORT 不可以与簇索引一起使用

ORA-01717: seccta: 访问已过时的模式标记无效

ORA-01718: NOAUDIT 不允许 BY ACCESS | SESSION 子句

ORA-01719: OR 或 IN 操作数中不允许外部连接运算符 (+)

错误触发:旧式联接(+)中,where条件使用 (c.gnwz_xlfl(+)<>'连接导线' or c.gnwz_xlfl is null)时报错。

错误解决:这是旧式关联不支持的语法,改用新式关联(left join)。

例一:报错的旧式关联

SELECT *

FROM tmp_em_m_tree v, b$common_n a

, b$gg_pd_gnwzmc_n c

WHERE a.cd_ssdw = v.NAME

AND a.ltt_id = 0

AND a.g3e_fno = 156

and a.g3e_fid = c.g3e_fid(+)

and c.ltt_id(+) = 0

and (c.gnwz_xlfl(+) <> '连接导线' or c.gnwz_xlfl(+) is null);

例二:通过的新式关联

SELECT *

FROM tmp_em_m_tree v,b$common_n a

left join b$gg_pd_gnwzmc_n c

on a.g3e_fid = c.g3e_fid

and c.ltt_id = 0

and (c.gnwz_xlfl <> '连接导线' or c.gnwz_xlfl is null)

WHERE a.cd_ssdw = v.NAME

AND a.ltt_id = 0

AND a.g3e_fno = 156;

ORA-01720: 授权选项对于'.'不存在

ORA-01721: USERENV(COMMITSCN) 在事务处理中调用了多次

ORA-01722: 无效数字

说明:当内嵌sql语句不能有效地将字符转变成数字时,会隐含地触发此异常。

ORA-01723: 不允许长度为 0 的列

错误说明:当create table时存在null列,则会报此错误

ORA-01724: 浮点(数)精确度超出范围(1 到 126)

ORA-01725: 此处不允许 USERENV('COMMITSCN')

ORA-01726: 此处不允许有表

ORA-01727: 数字精度说明符超出范围(1 到 38)

ORA-01728: 数字标度说明符超出范围(-84 到 127)

ORA-01729: 需要数据库链接名

ORA-01730: 指定的列名数无效

ORA-01731: 出现循环的视图定义

ORA-01732: 此视图的数据操纵操作非法

ORA-01733: 此处不允许虚拟列

ORA-01734: 非法的参数 - EXTENT MIN 高于 EXTENT MAX

ORA-01735: 非法的 ALTER TABLE 选项

ORA-01736: 需要 [NOT] SUCCESSFUL
ORA-01737: 有效模式: [ROW] SHARE, [[SHARE] ROW] EXCLUSIVE, SHARE UPDATE

说明:执行Lock table temp_liutao in 3 mode;时报的错误,因为mode没有选对。

解决:选择正确的模式。

ORA-01738: 缺少 IN 关键字

ORA-01739: 缺少 MODE 关键字

ORA-01740: 标识中缺少双引号

ORA-01741: 非法的零长度标识

ORA-01742: 备注错误终止

ORA-01743: 仅能编制纯函数的索引

ORA-01744: 不合理的 INTO

ORA-01745: 无效的主机/赋值变量名

ORA-01746: 此处不允许指示符变量

ORA-01747: 无效的用户.表.列,表.列,或列规格

ORA-01748: 此处只允许简单的列名

ORA-01749: 用户不可以自/至自己 GRANT/REVOKE 权限

ORA-01750: UPDATE/REFERENCES 仅可以从整个表而不能按列 REVOKE

ORA-01751: 无效的转储撤消选项

ORA-01752: 不能从没有一个键值保存表的视图中删除

ORA-01753: 列定义与聚簇列定义不兼容

ORA-01754: 表只能包含一个 LONG 类型的列

ORA-01755: 必须指定区编号或块编号

ORA-01756: 括号内的字符串没有正确结束

说明:如果中文某些字引起这个错误,是由于编码引起的,可以用类似Notepad软件对文本进行转码。

ORA-01757: 必须指定对象编号

ORA-01758: 要添加法定 (NOT NULL) 列,则表必须为空

ORA-01759: 未正确定义用户函数

ORA-01760: 函数的参数非法

ORA-01761: DML 操作与连结中的唯一表不对应

ORA-01762: vopdrv: FROM 中没有视图查询块

ORA-01763: 更新或删除涉及到外部连结表

ORA-01764: 连结的新更新值不能保证为唯一

ORA-01765: 不允许指定表的所有者名

ORA-01766: 此上下文中不允许有字典表

ORA-01767: UPDATE ...SET 表达式必须是子查询

ORA-01768: 数字字符串过长

ORA-01769: 重复的 CLUSTER 选项说明

ORA-01770: CREATE CLUSTER 命令中不允许有 CLUSTER 选项

ORA-01771: 选项对聚簇表非法

ORA-01772: 必须指定 LEVEL 的值

ORA-01773: 此 CERATE TABLE 中没有指定列的数据类型

ORA-01774: 转储撤消选项指定了多次

ORA-01775: 同义词的循环嵌套链

ORA-01776: 无法通过连接视图修改多个基表

ORA-01777: 此系统中不允许 WITH GRANT OPTION

ORA-01778: 超出最大子查询的嵌套层

ORA-01779: 无法修改与非键值保存表对应的列

ORA-01780: 要求文字字符串

ORA-01781: UNRECOVERABLE 不能指定没有 AS SELECT

ORA-01782: 不能为群集或聚簇表指定 UNRECOVERABLE

ORA-01783: 只可以指定 RECOVERABLE 或 UNRECOVERABLE 子句

ORA-01784: 不能指定 RECOVERABLE 具有禁用的数据库介质恢复

ORA-01785: ORDER BY 项必须是 SELECT-list 表达式的数目

ORA-01786: 此查询表达式不允许 FOR UPDATE

ORA-01787: 每个查询块只允许有一个子句

ORA-01788: 此查询块中要求 CONNECT BY 子句

ORA-01789: 查询块具有不正确的结果列数

ORA-01790: 表达式必须具有与对应表达式相同的数据类型

ORA-01791: 不是 SELECTed 表达式

ORA-01792: 表或视图中的最大列数为 1000

错误说明:ORACLE支持表或试图最多列数为1000,每一个块最大支持255列

ORA-01793: 索引列的最大数为 32

ORA-01794: 群集列的最大数目为 32

ORA-01795: 列表中的最大表达式数为 1000

ORA-01796: 此运算符不能与列表一起使用

ORA-01797: 此运算符后面必须跟 ANY 或 ALL

ORA-01798: 缺少 EXCEPTION 关键字

ORA-01799: 列不可以外部连接到子查询

ORA-01800: 日期格式中的文字过长以致无法处理

ORA-01801: 日期格式对于内部缓冲区过长

ORA-01802: Julian 日期超出范围

ORA-01803: 无法获得日期/时间

ORA-01804: 时区信息无法初始化

ORA-01810: 格式代码出现两次

ORA-01811: Julian 日期导致年度中的日无法使用

ORA-01812: 只可以指定一次年度

ORA-01813: 只可以指定一次小时

ORA-01814: AM/PM 因使用 A.M./P.M. 而发生冲突

ORA-01815: BC/AD 因使用 B.C./A.D. 而发生冲突

ORA-01816: 只可以指定一次月份

ORA-01817: 只可以指定一次周中的日

ORA-01818: 'HH24' 导致上下午指示符无法使用

ORA-01819: 带符号的年度导致 BC/AD 无法使用

ORA-01820: 格式代码无法以日期输入格式显示

ORA-01821: 日期格式无法识别

ORA-01822: 此日历的纪元格式代码无效

ORA-01830: 日期格式图片在转换整个输入字符串之前结束

ORA-01831: 年度与 Julian 日期发生冲突

ORA-01832: 年度中的日与 Julian 日期发生冲突

ORA-01833: 月份与 Julian 日期发生冲突

ORA-01834: 月份中的日与 Julian 日期发生冲突

ORA-01835: 周中的日与 Julian 日期发生冲突

ORA-01836: 小时与日中的秒发生冲突

ORA-01837: 小时中的分与日中的秒发生冲突

ORA-01838: 分中的秒与日中的秒发生冲突

ORA-01839: 指定月份的日期无效

ORA-01840: 输入值对于日期格式不够长

英文解析:input value not long enough for date format

错误解析:我在用SQLLDR导入数据的时候遇到此错误

ORA-01841: (全)年度值必须介于 -4713 和 +9999 之间,且不为 0

ORA-01842: 季度值必须介于 1 和 4 之间

ORA-01843: 无效的月份

错误说明:当向一个TIMESTAMP类型的字段插入一个to_char后的字符会报这个错误。

ORA-01844: 年度中的周值必须介于 1 和 52 之间

ORA-01845: 月份中的周值必须介于 1 和 5 之间

ORA-01846: 周中的日无效

ORA-01847: 月份中日的值必须介于 1 和当月最后一日之间

错误产生:当使用nvl函数针对date类型做nvl(date_type,' ')处理的时候便会报此类错误。

错误原因:date类型字段不能存放空格值。

ORA-01848: 年度中的日值必须介于 1 和 365 之间(闰年为 366)

ORA-01849: 小时值必须介于 1 和 12 之间

ORA-01850: 小时值必须介于 0 和 23 之间

ORA-01851: 分钟值必须介于 0 和 59 之间

ORA-01852: 秒值必须介于 0 和 59 之间

ORA-01853: 日中的秒值必须介于 0 和 86399 之间

ORA-01854: julian 日期必须介于 1 和 5373484 之间

ORA-01855: 要求 AM/A.M. 或 PM/P.M.

ORA-01856: 要求 BC/B.C. 或 AD/A.D.

ORA-01857: 无效的时区

ORA-01858: 在要求输入数字处找到非数字字符

ORA-01859: 在要求输入字母处找到非字母字符

ORA-01860: 年度中的周值必须介于 1 和 53 之间

ORA-01861: 文字与格式字符串不匹配

ORA-01862: 数字值与格式项目的长度不匹配

ORA-01863: 年度不支持当前日历

ORA-01864: 日期超出当前日历的范围

ORA-01865: 无效的纪元

ORA-01866: 日期时间类无效

ORA-01867: 间隔无效

ORA-01868: 间隔的前导精度太小

ORA-01869: 保留以供将来使用

ORA-01870: 间隔或日期时间不是相互可比较的

ORA-01871: 秒数必须少于 60

ORA-01872: 保留以供将来使用

ORA-01873: 间隔的前导精度太小

ORA-0

使用portforwarding连接TimesTen

$
0
0
windows主机上安装了TimesTen Client,然后主机上通过VirtualBox虚拟出linux Guest OS,安装了TimesTen Server。
由于虚拟机配置的是NAT网络,缺省情况下,虚拟机对于主机是不可见的,因此也无法作为服务器使用。有两种方法可以解决问题:
更改网络为Bridged Network 设置NAT网络的port forwarding

这里讨论第2种方法,也即将主机接收到的请求转发给虚拟机。

在NAT设置下,Guest OS的IP如下:

[timesten@localhost ~]$ ifconfig -a
eth0 Link encap:Ethernet HWaddr 08:00:27:45:AB:7A
inet addr:10.0.2.100 Bcast:10.0.2.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fe45:ab7a/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:167 errors:0 dropped:0 overruns:0 frame:0
TX packets:206 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:18231 (17.8 KiB) TX bytes:25049 (24.4 KiB)

Guest OS可以ping主机的IP:

[timesten@localhost ~]$ ping 192.168.56.1
PING 192.168.56.1 (192.168.56.1) 56(84) bytes of data.
64 bytes from 192.168.56.1: icmp_seq=1 ttl=127 time=1.70 ms
64 bytes from 192.168.56.1: icmp_seq=2 ttl=127 time=1.17 ms

Host OS的地址是在VirtualBox Host-Only Network中自动定义的。


使用portforwarding连接TimesTen

而HZ

【mybatis深度历险系列】mybatis中的高级映射一对一、一对多、多对多

$
0
0

学习hibernate的时候,小编已经接触多各种映射,mybatis中映射有到底是如何运转的,今天这篇博文,小编主要来简单的介绍一下mybatis中的高级映射,包括一对一、一对多、多对多,希望多有需要的小伙伴有帮助,小编主要从四个方面进行介绍,订单商品数据模型、一对一查询、一对多查询、多对多查询。

一、订单商品数据模型

1、数据库执行脚本,如下所示:

CREATE TABLE items (
id INT NOT NULL AUTO_INCREMENT,
itemsname VARCHAR(32) NOT NULL COMMENT '商品名称',
price FLOAT(10,1) NOT NULL COMMENT '商品定价',
detail TEXT COMMENT '商品描述',
pic VARCHAR(64) DEFAULT NULL COMMENT '商品图片',
createtime DATETIME NOT NULL COMMENT '生产日期',
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;
/*Table structure for table `orderdetail` */
CREATE TABLE orderdetail (
id INT NOT NULL AUTO_INCREMENT,
orders_id INT NOT NULL COMMENT '订单id',
items_id INT NOT NULL COMMENT '商品id',
items_num INT DEFAULT NULL COMMENT '商品购买数量',
PRIMARY KEY (id),
KEY `FK_orderdetail_1` (`orders_id`),
KEY `FK_orderdetail_2` (`items_id`),
CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) DEFAULT CHARSET=utf8;
/*Table structure for table `orders` */
CREATE TABLE orders (
id INT NOT NULL AUTO_INCREMENT,
user_id INT NOT NULL COMMENT '下单用户id',
number VARCHAR(30) NOT NULL COMMENT '订单号',
createtime DATETIME NOT NULL COMMENT '创建订单时间',
note VARCHAR(100) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
KEY `FK_orders_1` (`user_id`),
CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) DEFAULT CHARSET=utf8;
/*Table structure for table `t_user` */
CREATE TABLE t_user (
id INT NOT NULL AUTO_INCREMENT,
username VARCHAR(32) NOT NULL COMMENT '用户名称',
birthday DATE DEFAULT NULL COMMENT '生日',
sex CHAR(1) DEFAULT NULL COMMENT '性别',
address VARCHAR(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
测试数据代码
/*Data for the table `items` */
INSERT INTO items(itemsname,price,detail,pic,createtime) VALUES
('台式机',3000.0,'该电脑质量非常好!',NULL,'2015-07-07 13:28:53'),
('笔记本',6000.0,'笔记本性能好,质量好!',NULL,'2015-07-08 13:22:57'),
('背包',200.0,'名牌背包,容量大质量好!',NULL,'2015-07-010 13:25:02');
/*Data for the table `orderdetail` */
INSERT INTO `orderdetail`(`orders_id`,`items_id`,`items_num`) VALUES
(1,1,1),
(1,2,3),
(2,3,4),
(3,2,3);
/*Data for the table `orders` */
INSERT INTO `orders`(`user_id`,`number`,`createtime`,`note`) VALUES
(1,'1000010','2015-06-04 13:22:35',NULL),
(1,'1000011','2015-07-08 13:22:41',NULL),
(2,'1000012','2015-07-17 14:13:23',NULL),
(3,'1000012','2015-07-16 18:13:23',NULL),
(4,'1000012','2015-07-15 19:13:23',NULL),
(5,'1000012','2015-07-14 17:13:23',NULL),
(6,'1000012','2015-07-13 16:13:23',NULL);
/*Data for the table `user` */
INSERT INTO `t_user`(`username`,`birthday`,`sex`,`address`) VALUES
('王五',NULL,'2',NULL),
('张三','2014-07-10','1','北京市'),
('张小明',NULL,'1','河南郑州'),
('陈小明',NULL,'1','河南郑州'),
('张三丰',NULL,'1','河南郑州'),
('陈小明',NULL,'1','河南郑州'),
('王五',NULL,NULL,NULL),
('小A','2015-06-27','2','北京'),
('小B','2015-06-27','2','北京'),
('小C','2015-06-27','1','北京'),
('小D','2015-06-27','2','北京');
2、数据模型分析思路

(1).每张表记录的数据内容:分模块对每张表记录的内容进行熟悉,相当于你学习系统需求(功能)的过程;

(2).每张表重要的字段设置:非空字段、外键字段;

(3).数据库级别表与表之间的关系:外键关系;

(4).表与表之间的业务关系:在分析表与表之间的业务关系时一定要建立在某个业务意义基础上去分析。

3、针对订单商品模型的数据库思路分析,如下图所示:


【mybatis深度历险系列】mybatis中的高级映射一对一、一对多、多对多
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" />

二、一对一查询

2.1、需求:查询订单信息,关联查询用户信息

2.2、resultType实现

2.2.1sql语句

确定查询的主表:订单表,确定查询的关联表,用户表,代码如下所示:

SELECT t1.*,
t2.username,
t2.sex,
t2.address
FROM
orders t1,
t_user t2
WHERE t1.user_id=t2.id

2.2.2创建entity实体

用户实体User.java,代码如下所示:

package com.mybatis.entity;
import java.util.Date;
import java.util.List;
/**
* @ClassName: User
* @Description: TODO(用户实体)
* @author 阿赫瓦里
*/
public class User {
private Integer id;
// 姓名
private String username;
// 性别
private String sex;
// 地址
private String address;
// 生日
private Date birthday;
// 用户创建的订单列表
private List ordersList;
// getter and setter ......
}
订单实体orders.java
package com.mybatis.entity;
import java.util.Date;
import java.util.List;
/**
* @ClassName: Orders
* @Description: TODO(订单实体)
* @author 阿赫瓦里
*/
public class Orders {
/** 主键订单Id */
private Integer id;
/** 下单用户id */
private Integer userid;
/** 订单号 */
private String number;
/** 创建订单时间 */
private Date createTime;
/** 备注 */
private String note;
// 用户信息
private User user;
// 订单明细
private List orderdetails;
// getter and setter ......
}
商品实体:items.java
package com.mybatis.entity;
import java.util.Date;
/**
* @ClassName: Items
* @Description: TODO(商品实体类)
* @author 丁国华
*/
public class Items {
/** 商品表主键Id */
private Integer id;
/** 商品名称 */
private String itemsName;
/** 商品定价 */
private float price;
/** 商品描述 */
private String detail;
/** 商品图片 */
private String picture;
/** 生产日期 */
private Date createTime;
// getter and setter ......
}
订单明细实体orderDetail.java
package com.mybatis.entity;
/**
* @ClassName: OrderDetail
* @Description: TODO(订单明细实体)
* @author 丁国华
*/
public class OrderDetail {
/** 主

数据库中间件Mycat源码解析(三):Mycat的SQL解析和路由

$
0
0

mycat对sql的解析分为两部分,一个是普通sql,另一个是PreparedStatment。

下面以解析普通sql为例分析(另一种方式大同小异),sql从客户端发过来后server接收后会调用FrontendCommandHandler的handle方法,这个方法会调用FrontendConnection的query方法,接着query方法会调用ServerQueryHandler的query方法,接着调用ServerConnection的execute方法。如下图所示:

public void execute(String sql, int type) {
//连接状态检查
if (this.isClosed()) {
LOGGER.warn("ignore execute ,server connection is closed " + this);
return;
}
// 事务状态检查
if (txInterrupted) {
writeErrMessage(ErrorCode.ER_YES,
"Transaction error, need to rollback." + txInterrputMsg);
return;
}
// 检查当前使用的DB
String db = this.schema;
boolean isDefault = true;
if (db == null) {
db = SchemaUtil.detectDefaultDb(sql, type);
if (db == null) {
writeErrMessage(ErrorCode.ERR_BAD_LOGICDB, "No MyCAT Database selected");
return;
}
isDefault = false;
}
// 兼容phpAdmin's, 支持对mysql元数据的模拟返回
//// TODO: 2016/5/20 支持更多information_schema特性
if (ServerParse.SELECT == type
&& db.equalsIgnoreCase("information_schema") ) {
MysqlInformationSchemaHandler.handle(sql, this);
return;
}
if (ServerParse.SELECT == type
&& sql.contains("mysql")
&& sql.contains("proc")) {
SchemaUtil.SchemaInfo schemaInfo = SchemaUtil.parseSchema(sql);
if (schemaInfo != null
&& "mysql".equalsIgnoreCase(schemaInfo.schema)
&& "proc".equalsIgnoreCase(schemaInfo.table)) {
// 兼容MySQLWorkbench
MysqlProcHandler.handle(sql, this);
return;
}
}
SchemaConfig schema = MycatServer.getInstance().getConfig().getSchemas().get(db);
if (schema == null) {
writeErrMessage(ErrorCode.ERR_BAD_LOGICDB,
"Unknown MyCAT Database '" + db + "'");
return;
}
//fix navicat SELECT STATE AS `State`, ROUND(SUM(DURATION),7) AS `Duration`, CONCAT(ROUND(SUM(DURATION)/*100,3), '%') AS `Percentage` FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID= GROUP BY STATE ORDER BY SEQ
if(ServerParse.SELECT == type &&sql.contains(" INFORMATION_SCHEMA.PROFILING ")&&sql.contains("CONCAT(ROUND(SUM(DURATION)/*100,3)"))
{
InformationSchemaProfiling.response(this);
return;
}
/* 当已经设置默认schema时,可以通过在sql中指定其它schema的方式执行
* 相关sql,已经在mysql客户端中验证。
* 所以在此处增加关于sql中指定Schema方式的支持。
*/
if (isDefault && schema.isCheckSQLSchema() && isNormalSql(type)) {
SchemaUtil.SchemaInfo schemaInfo = SchemaUtil.parseSchema(sql);
if (schemaInfo != null && schemaInfo.schema != null && !schemaInfo.schema.equals(db)) {
SchemaConfig schemaConfig = MycatServer.getInstance().getConfig().getSchemas().get(schemaInfo.schema);
if (schemaConfig != null)
schema = schemaConfig;
}
}
routeEndExecuteSQL(sql, type, schema);
}
最后有个routeEndExecuteSQL方法,它会首先调用RouteService的route方法先进行路由,然后调用HintSQLHandler的route方法,这个方法里调用RouteStrategy的route方法,这里使用了一个策略模式,包含下面几种sql类型,不同类型使用不同策略。
public final class ServerParse {
public static final int OTHER = -1;
public static final int BEGIN = 1;
public static final int COMMIT = 2;
public static final int DELETE = 3;
public static final int INSERT = 4;
public static final int REPLACE = 5;
public static final int ROLLBACK = 6;
public static final int SELECT = 7;
public static final int SET = 8;
public static final int SHOW = 9;
public static final int START = 10;
public static final int UPDATE = 11;
public static final int KILL = 12;
public static final int SAVEPOINT = 13;
public static final int USE = 14;
public static final int EXPLAIN = 15;
public static final int EXPLAIN2 = 151;
public static final int KILL_QUERY = 16;
public static final int HELP = 17;
public static final int MYSQL_CMD_COMMENT = 18;
public static final int MYSQL_COMMENT = 19;
public static final int CALL = 20;
public static final int DESCRIBE = 21;
public static final int LOAD_DATA_INFILE_SQL = 99;
public static final int DDL = 100;
使用不同的路由方法是在routeNormalSqlWithAST中决定的,
public RouteResultset routeNormalSqlWithAST(SchemaConfig schema,
String stmt, RouteResultset rrs, String charset,
LayerCachePool cachePool) throws SQLNonTransientException {
/**
* 只有mysql时只支持mysql语法
*/
SQLStatementParser parser = null;
if (schema.isNeedSupportMultiDBType()) {
parser = new MycatStatementParser(stmt);
} else {
parser = new MySqlStatementParser(stmt);
}
MycatSchemaStatVisitor visitor = null;
SQLStatement statement;
/**
* 解析出现问题统一抛SQL语法错误
*/
try {
statement = parser.parseStatement();
visitor = new MycatSchemaStatVisitor();
} catch (Exception t) {
LOGGER.error("DruidMycatRouteStrategyError", t);
throw new SQLSyntaxErrorException(t);
}
/**
* 检验unsupported statement
*/
checkUnSupportedStatement(statement);
DruidParser druidParser = DruidParserFactory.create(schema, statement, visitor);
druidParser.parser(schema, rrs, statement, stmt,cachePool,visitor);
/**
* DruidParser 解析过程中已完成了路由的直接返回
*/
if ( rrs.isFinishedRoute() ) {
return rrs;
}
/**
* 没有from的select语句或其他
*/
DruidShardingParseInfo ctx= druidParser.getCtx() ;
if((ctx.getTables() == null || ctx.getTables().size() == 0)&&(ctx.getTableAliasMap()==null||ctx.getTableAliasMap().isEmpty()))
{
return RouterUtil.routeToSingleNode(rrs, schema.getRandomDataNode(), druidParser.getCtx().getSql());
}
if(druidParser.getCtx().getRouteCalculateUnits().size() == 0) {
RouteCalculateUnit routeCalculateUnit = new RouteCalculateUnit();
druidParser.getCtx().addRouteCalculateUnit(routeCalculateUnit);
}
SortedSet nodeSet = new TreeSet();
for(RouteCalculateUnit unit: druidParser.getCtx().getRouteCalculateUnits()) {
RouteResultset rrsTmp = RouterUtil.tryRouteForTables(schema, druidParser.getCtx(), unit, rrs, isSelect(statement), cachePool);
if(rrsTmp != null) {
for(RouteResultsetNode node :rrsTmp.getNodes()) {
nodeSet.add(node);
}
}
}
RouteResultsetNode[] nodes = new RouteResultsetNode[nodeSet.size()];
int i = 0;
for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
nodes[i] = iterator.next();
i++;
}
rrs.setNodes(nodes);
//分表
/**
* subTables="t_order$1-2,t_order3"
*目前分表 1.6 开始支持

Handling Big Data

$
0
0

A user on the Qlik blog asked the question “How do you handle ‘Big Data’?”

Being a technology vendor that focuses on this exact area, I wanted to share some of our observations. I hope that my unavoidable vendor-biased perspective will be balanced with some useful info.

Most people that use BI on large datasets in Hadoop take the approach of selective extract (into a QVD or TDE) and loading into memory. The discussion here, however, is what to do when the extract and load method is not a practical option because the extract itself is still too big, the lag time is too high, or other reasons. In such case, live access to the data at its source (Direct Discovery, Live Connect) is the preferable approach.

Indeed, Tableau’s Live Connect is the more mature interface, but Qlik’s Direct Discovery can be made to overcome its key limitations and provide a similar functionality. Specifically, the integration work done by Jethro and Qlik addresses the following issues:

Ability to map complex data model eg star schema) into Direct Discovery Enable in-DB functionality that emulates Qlik’s set analysis functionality and syntax

A great video by David Freriks, a Technology Evangelist on the Innovation and Design team at Qlik, demonstrating this solution:

Once you are able to connect your BI tool live to your datasets in Hadoop, you’re likely to encounter the next challenge: the performance of SQL-on-Hadoop tools (eg Hive) is usually too slow for any acceptable interaction. As noted earlier, there is constant progress being made in this area and the latest versions of Impala and Hawq are significantly faster that earlier releases. Still, the architecture used by all of these tools is nearly identical: they are all MPP / full scan engines. And while this architecture was effective with hi-end appliances (eg Teradata), it is less efficient with the switch to off-the shelf hardware, especially when combined with much larger dataset sizes, and more complex workloads.

At Jethro, we address this issue by using a different architecture: full indexing. By pre-indexing all the columns, Jethro can serve typical BI queries much faster than the full-scan based engines and with significantly less cluster resources.

We have a live demo of Jethro + Qlik available at: Qlik Sense .

See original blog post and comment thread here .

Redis初识(一)

$
0
0

首先,学习redis之前要给自己提出几个问题。

1、什么是redis?

2,、redis的使用?

3、redis的原理?

4、redis适合的应用场景?

那么,接下来,先解决第一个问题,什么是redis:

reidis的介绍网上有很多,不多说,红色标记一下重点。

Redis 是一个开源(BSD许可:是一个给于使用者很大自由的协议,BSD 代码鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销售,因此是对商业集成很友好的协议。而很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件. 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询. Redis 内置了 复制(replication), LUA脚本(Lua scripting), LRU驱动事件(LRU eviction), 事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过Redis哨兵(Sentinel) 和自动 分区(Cluster)提供高可用性(high availability).

你可以对这些类型执行 原子操作 , 列如: 字符串(strings)的append 命令; 散列(hashes)的hincrby命令; 列表(lists)的lpush命令; 集合(sets)计算交集sinter命令, 计算并集union命令 和 计算差集sdiff命令; 或者 在有序集合(sorted sets)里面获取成员的最高排名zrangebyscore命令.

为了实现其卓越的性能, Redis 采用运行在 内存中的数据集工作方式. 根据使用情况,可以每隔一定时间将 数据集导出到磁盘 , 或者 追加到命令日志中. 您也可以关闭持久化功能,将Redis作为一个高效的网络的缓存数据功能使用.

Redis 同样支持 主从复制(能自动重连和网络断开时自动重新同步),并且第一次同步是快速的非阻塞式的同步.

其他功能包括: 事务(Transactions) 订阅分发(Pub/Sub) LUA脚本(Lua scripting) 过期自动删除key 内存回收 自动故障转移您可以使用 大多数的编程语言 来使用Redis.

Redis 使用 ANSI C 编写并且能在绝大linux系统上运行,基于BSD协议,对OS X没有外部依赖. 我们支持Linux 和 OS X两种系统的开发和测试,我们推荐使用Linux部署. Redis 可以像SmartOS一样运行在Solaris系统中, 但是我们会最大力度的支持它. 官方不支持Windos版本的Redis,但微软开发和维护着支持win-64 的Redis版本.

------------------------------------------------------------分割线----------------------------------------------------------------------

redis作为一个非关系型数据库,命令行比较多,现在只是针对最常用的操作数据类型的命令说明:

String类型:1、set key value 增加数据

2、setnx key value 仅仅当key不存在时才能set成功,返回1,否则0;

3,、setex key seconds value 设置key的过期时间单位秒

4、mset key value [key value ...] 同时设置多个key value

5、msetnx 只用当key不存在时才能set 成功

6、get key 获取key 的value

7、mget 获取多个key的value

8、getrange key start end 获取存储在key中value的字串。字符串的截取有start和end决定

9、getset key value 设置key的value,并返回key的旧值

10、append key value key存在,在旧值后追加,不存在直接set

11、setrange key offset value 重写key的值得一部分,由offset决定

12、incr key 中如果存储的是数字,则可以通过incr递增key的值,返回递增后的值。如果key不能存在,视为初始值为0

13、incrby key increment 用increment 指定步长,增加key存储的值,如果步长是负数则减

14、decr 与incr相反,decrby与incrby相反

15、del key [key] 删除key 并返回删除的个数

16、strlen key 获取key中value的长度

更多详细参考:http://redis.cn/commands.html#string

散列类型:1、hset key field value 将哈希表key的域field的值设为value

2、hget key field 返回哈希表key指定的field的值

3、hsetnx key field value 设置哈希表key的field的值,并且field不能存在,否则操作无效

4、hmset key field value [field value ...] 设置多个field的value

5、hmget key field field1 ,,,,获取多个field

6、hgetall key 获取key的所有的field 和 value

7、hdel key field1 field2 。。。删除多个field 和value

8、hlen key 返回哈希表中所有field的个数

9、hexists key field 判断哈希表中的field是否存在

10、hkeys key 返回key对应的所有field

11、 hvals key 获取哈希表中所用的values

12、hincrby key field increment 根据给定increment ,对key的field的值进行增长

更多详细参考:http://redis.cn/commands.html#hash

列表list类型:

1、lpush key value[value] 把一个或多个元素插入表头。如果是多个value时,按照从左到右的次序插。返回插入元素的个数

2、lpushx key value 插入一个表头元素,当且仅当列表key存在时,才能插入。返回列表中元素的个数

3、rpush key [value] 将一个或多个值插入到队列的队尾。多值时,从左到右依次添加。返回列表中元素个数

4、rpushx key value 讲值插入到列表队尾,当且仅当列表key存在时,才添加。返回列表元素个数

5、linsert key before|after pivot value 将值插入到pivot的前面或后面。返回列表元素个数。如果参照点pivot不存在不插入。如果有多个pivot,以离表头最近的为准

6、lindex key index 根据index查找value

7、lrange key start stop 获取指定开始和结束范围的一些列元素

8、lset key index value 设置列表指定索引的值,如果指定索引不存在则报错

9、ltrim key start stop 保留指定区域的元素,其他元素全部删除

10、lrem key count value 移除等于value的元素,当count>0时,从表头开始查找,移除count个;当count=0时,从表头开始查找,移除所有等于value的;当count<0时,从表尾开始查找,移除|count| 个。

11、rpop key 移除并返回表尾元素

12、lpop key 移除并返回表尾元素

13、llen key 获取列表长度

更多详细参考:http://redis.cn/commands.html#list

set集合类型:

1.sadd key vaule 往集合中插入一个元素,如果value值已存在集合中,则返回0,不会被重复插入。

2.sinter key1 key2 ... keyN 取出n个key之间的交集。比如 key1里面有值a,b,c,d,e,key2里面有d,e,f,sinter key1 key2返回d,e。

3.sunion key1 key2 ... keyN 取出n个key之间的并集。比如 key1里面有值a,b,c,d,e,key2里面有d,e,f,sunion key1 key2返回a,b,c,d,e,f。

4.sdiff key1 key2 取出n个key之间的差集。比如 key1里面有值a,b,c,d,e,key2里面有d,e,f,sdiff key1 key2返回a,b,c;反过来sdiff key2 key1返回f。

5. smembers key 返回key集合中所有的元素,结果是无序的。

6. sismember key value 查看value这个值是否在key集合中。存在返回1,不存在返回0。

7. scard key 返回集合中有多少个元素。

8. smove key1 key2 value 把value从key1中移到key2中去。

9.srem key value1 value2 ... valueN 从key集合中删掉某些元素。

更多详细参考:http://redis.cn/commands.html#set

sorted sets有序集合类型:

1、zadd key score member [[score member] [score member] ...] 增加一个或多个member【根据score排序】到有序集key中,如果member已经存在,只更新score。返回增加member个数,不包含已经存在的member
2、zrange key start stop [withscores] 返回有续集key中指定范围【通过索引 start stop】的member[及其score];

3、zcount key min max 统计key中score值介于min 和max之间的member个数

4、zscore key member 返回有续集key中member的score

5、zrevrange key start stop [withscores] 返回有续集key中指定范围[通过索引start stop]的member[及score],返回member根据score按降序排列
6、zrangebyscore key min max [withscores] [limit offset count] 返回有续集key中,score大于等于min并且小于等于max的member。返回结果按照score递增的次序排列。可选withscores决定返回结果集中仅仅返回member还是返回member和score;可选参数limit 指定返回结果的数量区间。
7、zrevrangescore key max min [withscores] [limit offset count] 返回有续集key中score<=max并且score>=min 的元素,返回结果根据score从大到小顺序排列。可选参数withscores决定结果集中是否包含score,可选参数limit 指定返回结果集范围。

8、zrank key member 根据score从低到高,返回member在有续集中的index

9、zrevrank key member 根据score从高到低排序,返回member在有序集key中的index

10、zcard key 返回有续集key的基数

11、zincrby key increment member 有续集key的member增加增量increment,返回增加后的score

更多详细:http://redis.cn/commands.html#sorted_set

有人问为什么redis效率比mysql快?

个人觉得,mysql是持久化存储,数据要存储在磁盘上,就要涉及到IO。而redis是内存存储,简单的key-value 形式存储,所以效率会快一点。

mongoDB基础知识2----基本操作(CRUD),索引(常见、全文、地理位置)

$
0
0
一、mongoDB基本使用
1-1.数据写入和查询
> show dbs
local 0.000GB
# 即使数据库不存在,使用use也会创建
> use changwenDB
switched to db changwenDB
# 插入数据
> db.changwenDB_collection.insert({x:1})
WriteResult({ "nInserted" : 1 })
> show dbs
changwenDB 0.000GB
local 0.000GB
# show collections是命令,而不是函数。函数有返回值,命令没有
> show collections
changwenDB_collection
# 查询
> db.changwenDB_collection.find()
{ "_id" : ObjectId("57bda3bca907419000a16bee"), "x" : 1 }
# _id是mongodb是系统自动生成的,全局不能重复,可以自己指定
> db.changwenDB_collection.insert({x:2,_id:1})
WriteResult({ "nInserted" : 1 })
> db.changwenDB_collection.insert({x:3,_id:1})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: changwenDB.changwenDB_collection index: _id_ dup key: { : 1.0 }"
}
})
> db.changwenDB_collection.find()
{ "_id" : ObjectId("57bda3bca907419000a16bee"), "x" : 1 }
{ "_id" : 1, "x" : 2 }
# 带参数的查询
> db.changwenDB_collection.find({x:1})
{ "_id" : ObjectId("57bda3bca907419000a16bee"), "x" : 1 }
# 多条插入
> for(i=0;i<10; i++)db.changwenDB_collection.insert({x:1})
WriteResult({ "nInserted" : 1 })
> db.changwenDB_collection.find()
{ "_id" : ObjectId("57bda3bca907419000a16bee"), "x" : 1 }
{ "_id" : 1, "x" : 2 }
{ "_id" : ObjectId("57bda4a5a907419000a16bef"), "x" : 1 }
{ "_id" : ObjectId("57bda4a5a907419000a16bf0"), "x" : 1 }
{ "_id" : ObjectId("57bda4a5a907419000a16bf1"), "x" : 1 }
{ "_id" : ObjectId("57bda4a5a907419000a16bf2"), "x" : 1 }
{ "_id" : ObjectId("57bda4a5a907419000a16bf3"), "x" : 1 }
{ "_id" : ObjectId("57bda4a5a907419000a16bf4"), "x" : 1 }
{ "_id" : ObjectId("57bda4a5a907419000a16bf5"), "x" : 1 }
{ "_id" : ObjectId("57bda4a5a907419000a16bf6"), "x" : 1 }
{ "_id" : ObjectId("57bda4a5a907419000a16bf7"), "x" : 1 }
{ "_id" : ObjectId("57bda4a5a907419000a16bf8"), "x" : 1 }
> db.changwenDB_collection.find().count()
12
> db.changwenDB_collection.find().skip(3).limit(2).sort({x:1})
{ "_id" : ObjectId("57bda4a5a907419000a16bf1"), "x" : 1 }
{ "_id" : ObjectId("57bda4a5a907419000a16bf2"), "x" : 1 }
>
1-2.数据更新
# 将x=1更新为x=99
> db.changwenDB_collection.update({x:1},{x:99})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.changwenDB_collection.find()
{ "_id" : ObjectId("57bda3bca907419000a16bee"), "x" : 99 }
{ "_id" : 1, "x" : 2 }
> db.changwenDB_collection.insert({x:100,y:100,z:100})
WriteResult({ "nInserted" : 1 })
> db.changwenDB_collection.find()
{ "_id" : ObjectId("57bee69ea907419000a16bfb"), "x" : 100, "y" : 100, "z" : 100 }
# 如果这么更新,会将,y,z覆盖,只剩下x
> db.changwenDB_collection.update({z:100},{x:99})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.changwenDB_collection.find()
{ "_id" : ObjectId("57bee69ea907419000a16bfb"), "x" : 99 }
# set部分更新
> db.changwenDB_collection.update({z:100},{$set:{x:99}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.changwenDB_collection.find()
{ "_id" : ObjectId("57bee82d97bc76e52551f81e"), "x" : 99, "y" : 100, "z" : 100 }
更新不存在的数据
# x=100不存在,就将x=111,(需要加true);存在则更新
> db.changwenDB_collection.update({x:100},{x:111},true)
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("57bee8f1eecfb943edb7f1e5")
})
更新多条数据:默认只能更新一条
> for(i=0;i<3; i++)db.changwenDB_collection.insert({x:1})
WriteResult({ "nInserted" : 1 })
> db.changwenDB_collection.find()
{ "_id" : ObjectId("57bee82d97bc76e52551f81e"), "x" : 99, "y" : 100, "z" : 100 }
{ "_id" : ObjectId("57bee8f1eecfb943edb7f1e5"), "x" : 111 }
{ "_id" : ObjectId("57beea1e97bc76e52551f81f"), "x" : 1 }
{ "_id" : ObjectId("57beea1e97bc76e52551f820"), "x" : 1 }
{ "_id" : ObjectId("57beea1e97bc76e52551f821"), "x" : 1 }
> db.changwenDB_collection.update({x:1},{$set:{x:2}},false,true)
WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 3 })
> db.changwenDB_collection.find()
{ "_id" : ObjectId("57bee82d97bc76e52551f81e"), "x" : 99, "y" : 100, "z" : 100 }
{ "_id" : ObjectId("57bee8f1eecfb943edb7f1e5"), "x" : 111 }
{ "_id" : ObjectId("57beea1e97bc76e52551f81f"), "x" : 2 }
{ "_id" : ObjectId("57beea1e97bc76e52551f820"), "x" : 2 }
{ "_id" : ObjectId("57beea1e97bc76e52551f821"), "x" : 2 }
1-3.数据删除

默认删除所有查找到的数据

> db.changwenDB_collection.remove({x:2})
WriteResult({ "nRemoved" : 3 })
> db.changwenDB_collection.find()
{ "_id" : ObjectId("57bee82d97bc76e52551f81e"), "x" : 99, "y" : 100, "z" : 100 }
{ "_id" : ObjectId("57bee8f1eecfb943edb7f1e5"), "x" : 111 }
# 删除表
> db.changwenDB_collection.drop()
true
> show tables
1-4.创建索引

数据量较大时,需要创建索引

> db.changwenDB_collection.insert({x:1})
WriteResult({ "nInserted" : 1 })
> db.changwenDB_collection.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.changwenDB_collection"
}
]
-- 创建索引,key值代表方法,1为正向,-1为负向。最好创建数据库前就创建索引
> db.changwenDB_collection.ensureIndex({x:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.changwenDB_collection.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.changwenDB_collection"
},
{
"v" : 1,
"key" : {
"x" : 1
},
"name" : "x_1",
"ns" : "test.changwenDB_collection"
}
]
二、常见的查询索引
2-1._id索引
1)._id索引是绝大多数集合默认建立的索引。
2).对于每个插入的数据,MongoDB都会自动生成一条唯一的_id字段。
2-2.单键索引
1).单键索引是最普通的索引
如,一条记录,形式为{x:1,y:2,z:3}
2).与_id索引不同,单键索引不会自动创建
--参数上面的代码,ensure就是单键索引
2-3.多键索引
1).多键索引与单键索引创建形式相同,区别在于字段的值。
单键索引:值为一个单一的值,例如字条串,数字或者日期
多键索引:值具有多个记录,如数组
-- 对于这条插入语名,MongoDB便创建了多键索引
> db.changwen2.insert({x:[1,2,3,4,5]})
WriteResult({ "nInserted" : 1 })
2-4.复合索引
1).当我们的查询条件不只胡一个时,就需要建立复合索引
如插入{x:1,y:2,z:3}记录
---> 如果按照x与y的值查询
---> 创建索引:db.collection.ensureIndex({x:1,y:1})
---> 使用{x:1,y:1}作为条件进行查询
> db.changwen2.ensureIndex({x:1,y:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.changwen2.find({x:1,y:2})
2-5.过期索引
1).是在一段时间后会过期的索引
2).在索引过期后,相应的数据会被删除
3).这适合存储一些在一段时间之后会失效的数据,比如用户的登录信息,存储的日志
4).建立方法:db.collection.ensureIndex({time:},(expireAfterSeconds:10}))
> db.changwen2.ensureIndex({time:1},{expireAfterSeconds:30})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"ok" : 1
}
> db.changwen2.insert({time:new Date()})
WriteResult({ "nInserted" : 1 })
> db.changwen2.find()
{ "_id" : ObjectId("57bef11697bc76e52551f823"), "x" : 1 }
{ "_id" : ObjectId("57bef87697bc76e52551f826"), "time" : ISODate("2016-08-25T13:53:58.190Z") }
> db.changwen2.find()
{ "_id" : ObjectId("57bef11697bc76e52551f823"), "x" : 1 }
-- 删除不了,对应限制2
> db.changwen2.insert({time:11})
WriteResult({ "nInserted" : 1 })
> db.changwen2.find()
{ "_id" : ObjectId("57bef11697bc76e52551f823"), "x" : 1 }
{ "_id" : ObjectId("57bef90197bc76e52551f827"), "time" : 11 }
过期索引的限制:
1).存储在过期索引字段的值必须是指定的时间类型
说明:必须是ISOData或者ISODate数组,不能使用时间戳,否则不能被自动删除
2).如果指定了ISODate数组,则按照最小的时间进行删除
3).过期索引不能是复合索引,因为不能指定两个过期时间
4).删除时间不是精确的。
说明:删除过程是由后台程序每60s跑一次,而且删除也需要一些时间,所以存在误差。
三、全文索引
全文索引:对字符串与字符串数组创建全文可搜索的索引
适用情况:{author:"",title:"",article:""}
3-1.创建全文索引方法
建立方法:
db.articles.ensureIndex({key:"text"})
db.articles.ensureIndex({key_1:"text",key_2:"text"})
db.articles.ensureIndex({"$**":"text"})
注意:key是字段名,但value是固定值
> db.changwen2.ensureIndex({"article":"text"})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 3,
"numIndexesAfter" : 4,
"ok" : 1
}
> db.changwen2.insert({"article":"aa bb cc dd ee"})
WriteResult({ "nInserted" : 1 })
> db.changwen2.insert({"article":"aa bb cc gg"})
WriteResult({ "nInserted" : 1 })
> db.changwen2.insert({"article":"aa bb cc rr"})
WriteResult({ "nInserted" : 1 })
3-2.使用全文索引进行查询
-- 查询含有aa的数据
db.articles.find({$text:{$search:"aa"}})
-- 查询含有aa,或bb,或cc的数据
db.articles.find({$text:{$search:"aa bb cc"}})
-- 查询含有aa,或bb,不含有cc的数据
db.articles.find({$text:{$search:"aa bb -cc"}})
-- 查询含有aa且含有bb且含有cc的数据
db.articles.find({$text:{$search:"\"aa\" \"bb\" \"cc\""}})
> db.changwen2.find({$text:{$search:"aa dd"}})
{ "_id" : ObjectId("57bf042b97bc76e52551f828"), "article" : "aa bb cc dd ee" }
{ "_id" : ObjectId("57bf043197bc76e52551f829"), "article" : "aa bb cc gg" }
{ "_id" : ObjectId("57bf043597bc76e52551f82a"), "article" : "aa bb cc rr" }
> db.changwen2.find({$text:{$search:"aa bb -dd"}})
{ "_id" : ObjectId("57bf043197bc76e52551f829"), "article" : "aa bb cc gg" }
{ "_id" : ObjectId("57bf043597bc76e52551f82a"), "article" : "aa bb cc rr" }
> db.changwen2.find({$text:{$search:"\"aa\" \"dd\""}})
{ "_id" : ObjectId("57bf042b97bc76e52551f828"), "article" : "aa bb cc dd ee" }
3-3.全文索引相似度查询
全文索引相似度:
$meta操作符:{score:{$meta:"textScore"}}
写在查询条件后面可以返回返回结果的相似度
与sort一起使用,可以达到很好的实用效果
> db.changwen2.insert({"article":"aa bb"})
WriteResult({ "nInserted" : 1 })
> db.changwen2.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}})
{ "_id" : ObjectId("57bf10a297bc76e52551f82b"), "article" : "aa bb", "score" : 1.5 }
{ "_id" : ObjectId("57bf043197bc76e52551f829"), "article" : "aa bb cc gg", "score" : 1.25 }
{ "_id" : ObjectId("57bf043597bc76e52551f82a"), "article" : "aa bb cc rr", "score" : 1.25 }
{ "_id" : ObjectId("57bf042b97bc76e52551f828"), "article" : "aa bb cc dd ee", "score" : 1.2 }
全文索引的使用限制
1).每次查询,只能指定一个$text查询
2).$text查询不能出现在$not查询中
3).查询中如果包含了$text,hint不再起作用
4).MongDB全文索引还不支持中文
四、地理位置索引
4-1.创建索引时重要的属性
创建索引时的格式:
db.collection.ensureIndex({param},{param})
其中第一个参数是索引的值,第二个参数是索引的属性
比较重要的属性有:
1).名字
名字,name指定:
db.collection.ensureIndex({},{name:""})
创建时,mongoDB会默认通过名字创建索引
> db.changwen2.ensureIndex({x:1})
-- 可以看到索引的名字由key_value组成"x_1",其中1和-1表示索引 的方向
> db.changwen2.getIndexes()
[
...
{
"v" : 1,
"key" : {
"x" : 1
},
"name" : "x_1",
"ns" : "changwen2.changwen2"
}
]
>
db.changwen2.ensureIndex({y:-1})
db.changwen2.ensureIndex({x:1,y:-1})
--那么结果会是"x_1_y_-1"
-- 如果名字很长,不好记,而且有长度限制。自定义为如下
db.changwen2.ensureIndex({x:1,y:1,z:1,m:1,{name:"normal_index"})
db.changwen2.dropIndex("normal_index")
2).唯一性
唯一性,unique指定
db.collection.ensureIndex({},{unique:true/false})
db.changwen2.ensureIndex({m:1,n:1},{unique:true})
db.changwen2.insert({m:2,n:3}})
-- 再次插入会有异常
db.changwen2.insert({m:2,n:3}})
3).稀疏性
sparse指定
db.collection.ensureIndex({},{spare:true/false})
默认情况下是不稀疏的,即如果没有这个索引,也会创建。指定稀疏性就不必为不存在的数据创建索引
db.changwen2.insert({m:5})
db.changwen2.insert({n:5})
-- 查找只存在m,不存在n的数据
db.changwen2.find({m:{$exists:true}})
-- 创建稀疏索引
db.changwen2.ensureIndex({m:1},{sparse:true})
-- 存在m不存在的数据
db.changwen2.find({m:{$exists:false}})
db.changwen2.getIndex()
-- hint强制使用索引
db.changwen2.find({m:{$exists:false}}).hint("m_1")
4).是否定时删除
expireAfterSecondes指定:
TTL,过期索引
4-2、地理位置索引介绍
概念:将一些点的位置存储在MongoDB中,创建索引后,可以按照位置来查找其他点。
子分类:
2d索引,用于存储和查找平面上的点
2dsphere索引,用于存储和查找球面上的点
查找方式:
1.查找距离某个点一定距离内的点
2.查找包含在某区域内的点
4-3.2d索引
2D索引:平面地理位置索引
创建方式:db.collection.ensureIndex({w:"2d"})
位置表示方式:经纬度[经度,纬度]
取值范围:经度[-180,180] 纬度[-90,90]
查询方式:
1).$near查询:查询某个距离某个点最近的点
2).$geoWithin查询:查询某个形状地点
形状的表示:
1).$box:矩形,使用{$box:[[,],[,]]}表示
2).$center:圆形,使用{$center:[[,],r]}表示
3).$polygon:多边形,使用{$polygon:[[,],[,],[,]]}表示
db.location.ensureIndex({w:"2d"})
db.location.insert({w:[1,1]})
db.location.insert({w:[1,2]})
db.location.insert({w:[3,2]})
db.location.insert({w:[50,50]})
db.location.insert({w:[180,50]})
-- near查询距离"1,1"最近的点,maxDistance限制最远点的距离是10
db.location.find({w:{$near:[1,1],$maxDistance:10}})
-- 在2d索引中不支持min查询
goeWithin查询
> db.location.find({w:{$geoWithin:{$box:[[0,0],[2,3]]}}})
{ "_id" : ObjectId("57c10675b5ef0e591d607d81"), "w" : [ 1, 1 ] }
{ "_id" : ObjectId("57c10681b5ef0e591d607d82"), "w" : [ 1, 2 ] }
> db.location.find({w:{$geoWithin:{$center:[[0,0],3]}}})
{ "_id" : ObjectId("57c10675b5ef0e591d607d81"), "w" : [ 1, 1 ] }
{ "_id" : ObjectId("57c10681b5ef0e591d607d82"), "w" : [ 1, 2 ] }
> db.location.find({w:{$geoWithin:{$polygon:[[0,0],[0,1],[2,5],[6,1]]}}})
{ "_id" : ObjectId("57c10675b5ef0e591d607d81"), "w" : [ 1, 1 ] }
{ "_id" : ObjectId("57c10681b5ef0e591d607d82"), "w" : [ 1, 2 ] }
{ "_id" : ObjectId("57c10686b5ef0e591d607d83"), "w" : [ 3, 2 ] }
比near更高级的查询--geoNear
geoNearr使用runCommand命令进行使用,常用使用如下:
db.runCommand({geoNear:,near:[x,y],
minDistance:(对2d索引无效)}
maxDistance:
num: .....)
> db.runCommand({geoNear:"location",near:[1,2],maxDistance:10,num:1})
{
"waitedMS" : NumberLong(0),
"results" : [
{
"dis" : 0,
"obj" : {
"_id" : ObjectId("57c10681b5ef0e591d607d82"),
"w" : [
1,
2
]
}
}
],
"stats" : {
"nscanned" : 3,
"objectsLoaded" : 1,
"avgDistance" : 0,
"maxDistance" : 0,
"time" : 0
},
"ok" : 1
}
4-4.2Dsphere索引
概念:球面地理位置索引
创建方式:db.collection.ensureIndex({w:"2dsphere"})
位置表示方式:
GeoJSON:描述一个点,一条直线,多边形等形状
格式:{type:"",coordinates:[]}
查询方式与2d索引查询方式类似,支持$minDistance与$maxDistance
4-5.如何评判当前索引构建情况
索引构建情况分析
索引好处:加快索引相关的查询
索引不好处:增加磁盘空间消耗,降低写入性能
如何评判当前索引构建情况
1).mongostat工具介绍
mongostat:查看mongodb运行状态的程序
使用说明:mongostat -h 127.0.0.1:12345
索引情况:idx miss
> for(i=0;i<10000;i++)db.changwen2.insert({x:i})
WriteResult({ "nInserted" : 1 })
--执行上面的语句后,立马执行下面的语句
changwen@ubuntu:~/user_project/mongodb_simple1/bin$ mongostat -h 127.0.0.1:12345
connected to: 127.0.0.1:12345
warning: detected a 3.0 mongod, some columns not applicable
insert query update delete getmore command mapped vsize res faults locked db idx miss % qr|qw ar|aw netIn netOut conn time
2415 *0 *0 *0 0 1|0 0m 263m 78m 0 Metadata:0.0% 0 0|0 0|0 306k 118k 2 21:11:48
2768 *0 *0 *0 0 1|0 0m 264m 79m 0 Metadata:0.0% 0 0|0 0|0 351k 132k 2 21:11:49
150 *0 *0 *0 0 2|0 0m 264m 79m 0 Metadata:0.0% 0 0|0 0|0 19k 25k 2 21:11:50
*0 *0 *0 *0 0 1|0 0m 264m 79m 0 Metadata:0.0% 0 0|0 0|0 62b 19k 2 21:11:51
*0 *0 *0 *0 0 1|0 0m 264m 79m 0 Metadata:0.0% 0 0|0 0|0 62b 19k 2 21:11:52
2).profile集合介绍
> db.getProfilingStatus()
{ "was" : 0, "slowms" : 100 }
--为0表示profile是关闭的,不会记录任何数据
--1,2
> db.setProfilingLevel(2)
{ "was" : 0, "slowms" : 100, "ok" : 1 }
> db.getProfilingStatus()
{ "was" : 2, "slowms" : 100 }
> show tables
changwen2
location
system.profile --这个是刚自动创建的
-- natural自然排序,是按输入先后时间
> db.system.profile.find().sort({$natural:-1}).limit(1)
{ "op" : "query", "ns" : "changwen2.system.profile", "query" : { "find" : "system.profile", "filter" : { } }, "keysExamined" : 0, "docsExamined" : 0, "cursorExhausted" : true, "keyUpdates" : 0, "writeConflicts" : 0, "numYield" : 1, "locks" : { "Global" : { "acquireCount" : { "r" : NumberLong(4) } }, "Database" : { "acquireCount" : { "r" : NumberLong(2) } }, "Collection" : { "acquireCount" : { "r" : NumberLong(2) } } }, "nreturned" : 0, "responseLength" : 115, "protocol" : "op_command", "millis" : 133, "execStats" : { "stage" : "COLLSCAN", "filter" : { "$and" : [ ] }, "nReturned" : 0, "executionTimeMillisEstimate" : 0, "works" : 2, "advanced" : 0, "needTime" : 1, "needYield" : 0, "saveState" : 1, "restoreState" : 1, "isEOF" : 1, "invalidates" : 0, "direction" : "forward", "docsExamined" : 0 }, "ts" : ISODate("2016-08-27T04:18:51.490Z"), "client" : "127.0.0.1", "allUsers" : [ ], "user" : "" }
3).日志介绍
在mongod.conf配置文件里配置,verbose=vvvvv
v最多5个,v越多越详细
4).explain分析
db.changwen2.find({x:1}).explain() 可以详细的看到索引的情况
五、mongoDB安全
1).最安全的是物理隔离:不现实
2).网络隔离其次,如使用内网
3).防火墙再其次
4).用户名密码在最后
5-1.开启权限认证
1).auth开启
在mongod.conf中配置auth=true,然后重启下
2).keyfile开启
5-2.在MongoDB中创建用户
1).创建语法:createUser(2.6之前为addUser)
2).{user:"",pwd:"",customData:{},
roles:[{role:"",db:""}]}
3).角色类型:内建类型(read,readWrite,dbAdmin,dbOwner,userAdmin)
> db.createUser({user:"changwensir",pwd:"changwensir",roles:[{role:"userAdmin",db:"admin"},{role:"read",db:"test"}]})
Successfully added user: {
"user" : "changwensir",
"roles" : [
{
"role" : "userAdmin",
"db" : "admin"
},
{
"role" : "read",
"db" : "test"
}
]
}
5-3.MongoDB用户角色详解
1).数据库角色(read,readWrite,dbAdmin,dbOwner,userAdmin)
2).集群权限(clusterAdmin,clusterManager...)
3).备份角色(backup,restore...)
4).其他特殊权限(DBAdminAnyDatabase...)

【SQLPerformance】历史SQL监控(HistoricalSQLMonitoring)功能(12c)

$
0
0

概述历史SQL监控使用的例子关于Automatic Report Capturing 相关视图和程序包相关参数参考

概述

Oracle 11g版本 推出了实时SQL监控功能(Real-Time SQL Monitoring),用于实时地监视执行中SQL的性能;Oracle 12c 对其进一步进行了扩展,推出了历史SQL监控功能(Historical SQL Monitoring)。

该功能类似于ASH信息的履历管理(DBA_HIST_ACTIVE_SESS_HISTORY),通过后台进程定期地把SQL的监视信息保存到数据库表中,以供事后分析SQL相关的问题。

关于11g的实时SQL监控功能,可查看上一篇文章:
【SQL Performance】实时SQL监控功能(Real-Time SQL Monitoring)
历史SQL监控使用的例子

首先通过以下历史SQL监控使用的例子来初步了解一下该功能。

测试例:(12.1.0.2.0)
1.准备数据
SQL> conn /as sysdba
Connected.
SQL> create user teacherwhat identified by teacherwhat;
User created.
SQL> grant dba to teacherwhat;
Grant succeeded.
SQL> conn teacherwhat/teacherwhat
Connected.
SQL> create table SQLMON(a varchar2(3),b varchar2(10),c varchar2(5));
Table created.
SQL> begin
for i in 1..1000
loop
insert into SQLMON values('A', i, 'A');
insert into SQLMON values('B', i, 'B');
end loop;
end;
/ 2 3 4 5 6 7 8
PL/SQL procedure successfully completed.
SQL> create index SQLMON_I on SQLMON(a,b,c);
Index created.
SQL> exec dbms_stats.gather_table_stats(OWNNAME => NULL, TABNAME => 'SQLMON', CASCADE => TRUE);
PL/SQL procedure successfully completed.

2.执行监视对象SQL文

--通过指定/*+ MONITOR */ Hint 使执行SQL成为SQL monitor功能监视对象
SQL> select/*+ MONITOR */ count(*) from SQLMON where a='A';
COUNT(*)
----------
1000

3.查看实时SQL监控的结果 (同11g)

SQL> SELECT sql_id, hash_value, substr(sql_text,1,40) sql_text
FROM v$sql
WHERE sql_text like 'select/*+ MONITOR */ count(*)%'; 2 3
SQL_ID HASH_VALUE
------------- ----------
SQL_TEXT
--------------------------------------------------------------------------------
bq20d7r8f6qa6 3504560454
select/*+ MONITOR */ count(*) from SQLMO
SQL> SET LONG 1000000
SQL> SET LONGCHUNKSIZE 1000000
SQL> SET LINESIZE 1000
SQL> SET PAGESIZE 0
SQL> SET TRIM ON
SQL> SET TRIMSPOOL ON
SQL> SET ECHO OFF
SQL> SET FEEDBACK OFF
SQL>
SQL> SELECT DBMS_SQLTUNE.report_sql_monitor(sql_id => 'bq20d7r8f6qa6', type => 'TEXT') AS report FROM dual;
SQL Monitoring Report
SQL Text
------------------------------
select/*+ MONITOR */ count(*) from SQLMON where a='A'
Global Information
------------------------------
Status : DONE (ALL ROWS)
Instance ID : 1
Session : TEACHERWHAT (237:24669)
SQL ID : bq20d7r8f6qa6
SQL Execution ID : 16777216
Execution Started : 08/25/2016 21:07:26
First Refresh Time : 08/25/2016 21:07:26
Last Refresh Time : 08/25/2016 21:07:26
Duration : .000518s
Module/Action : SQL*Plus/-
Service : SYS$USERS
Program : sqlplus@db12102 (TNS V1-V3)
Fetch Calls : 1
Global Stats
=======================================
| Elapsed | Other | Fetch | Buffer |
| Time(s) | Waits(s) | Calls | Gets |
=======================================
| 0.00 | 0.00 | 1 | 12 |
=======================================
SQL Plan Monitoring Details (Plan Hash Value=1559208047)
=================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | (%) | (# samples) |
=================================================================================================================================
| 0 | SELECT STATEMENT | | | | 1 | +0 | 1 | 1 | | |
| 1 | SORT AGGREGATE | | 1 | | 1 | +0 | 1 | 1 | | |
| 2 | INDEX FAST FULL SCAN | SQLMON_I | 1000 | 3 | 1 | +0 | 1 | 1000 | | |
=================================================================================================================================

4.查看历史SQL监控报告的结果

可以通过视图DBA_HIST_REPORTS和DBA_HIST_REPORTS_DETAILS来查看历史的SQL监控结果,也可以通过DBMS_AUTO_REPORT.REPORT_REPOSITORY_DETAIL包查看结果。

DBA_HIST_REPORTS :SQL Monitor、DBOP、Real-Time ADDM等报告的信息
DBA_HIST_REPORTS_DETAILS:各个报告的纤细信息

4.1 通过SQL_ID或者时间等其他条件,DBA_HIST_REPORTS中查找历史SQL监控报告的REPORT_ID。

SQL> SET LINESIZE 1000
SQL> col sql_id format a20
SQL> col sql_exec_id format a20
SQL> col sql_exec_start format a20
SQL> SELECT report_id, key1 sql_id, key2 sql_exec_id, key3 sql_exec_start
FROM dba_hist_reports where key1 ='bq20d7r8f6qa6'; 2
REPORT_ID SQL_ID SQL_EXEC_ID SQL_EXEC_START
---------- -------------------- -------------------- --------------------
20 bq20d7r8f6qa6 16777216 08:25:2016 21:07:26

4.2.通过DBMS_AUTO_REPORT.REPORT_REPOSITORY_DETAIL包来显示查看实时SQL监控结果。

---通过指定REPORT_ID来获得历史SQL监控报告。
SQL> set long 10000000 longchunksize 10000000 pages 0 LINESIZE 1000
SQL> SELECT DBMS_AUTO_REPORT.REPORT_REPOSITORY_DETAIL(RID => 20, TYPE => 'text') FROM dual;
SQL Monitoring Report
SQL Text
------------------------------
select/*+ MONITOR */ count(*) from SQLMON where a='A'
Global Information
------------------------------
Status : DONE (ALL ROWS)
Instance ID : 1
Session : TEACHERWHAT (237:24669)
SQL ID : bq20d7r8f6qa6
SQL Execution ID : 16777216
Execution Started : 08/25/2016 21:07:26
First Refresh Time : 08/25/2016 21:07:26
Last Refresh Time : 08/25/2016 21:07:26
Duration : .000518s
Module/Action : SQL*Plus/-
Service : SYS$USERS
Program : sqlplus@db12102 (TNS V1-V3)
Fetch Calls : 1
Global Stats
=======================================
| Elapsed | Other | Fetch | Buffer |
| Time(s) | Waits(s) | Calls | Gets |
=======================================
| 0.00 | 0.00 | 1 | 12 |
=======================================
SQL Plan Monitoring Details (Plan Hash Value=1559208047)
=================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | (%) | (# samples) |
=================================================================================================================================
| 0 | SELECT STATEMENT | | | | 1 | +0 | 1 | 1 | | |
| 1 | SORT AGGREGATE | | 1 | | 1 | +0 | 1 | 1 | | |
| 2 | INDEX FAST FULL SCAN | SQLMON_I | 1000 | 3 | 1 | +0 | 1 | 1000 | | |
=================================================================================================================================

通过上面的方法,我们可以对某些过去的SQL进行查看,这对某些问题的事后调查非常有用。

下面我们进一步了解该功能

关于”Automatic Report Capturing”

历史SQL监控(Historical SQL Monitoring ) 功能是12c新功能”Automatic Report Capturing”的一部分,通过MMON_SLAVE后台进程定期地把实时SQL监控的信息保存到数据库的相关表中。

下面我们通过以下测试,进一步了解一下这个动作。

测试:(12.1.0.2.0 Single Instance)

1.对MMON_SLAVE的’Automatic Report Flush’动作设置SQL Trace。

SQL> set line 180
SQL> col PRIMARY_ID format a20
SQL> col QUALIFIER_ID1 format a20
SQL>
SQL> select trace_type, primary_id, qualifier_id1, waits, binds from DBA_ENABLED_TRACES;
no rows selected
SQL> exec dbms_monitor.serv_mod_act_trace_enable -
(service_name=>'SYS$BACKGROUND',-
module_name=>'MMON_SLAVE',-
action_name=>'Automatic Report Flush',-
waits => true, -
binds => true);> > > > >
PL/SQL procedure successfully completed.
SQL> select trace_type, primary_id, qualifier_id1, waits, binds from DBA_ENABLED_TRACES;
TRACE_TYPE PRIMARY_ID QUALIFIER_ID1 WAITS BINDS
--------------------- -------------------- -------------------- ----- -----
SERVICE_MODULE_ACTION SYS$BACKGROUND MMON_SLAVE TRUE TRUE

2.查看trace路径,可以看到每隔一分钟系统生成一个Mxxx的跟踪文件。

[oracle@db12102 trace]$ pwd
/u01/app/oracle/diag/rdbms/ora12102/ora12102/trace
[oracle@db12102 trace]$ ls -larth
total 192K
drwxr-x--- 16 oracle oinstall 4.0K Apr 10 20:18 ..
-rw-r----- 1 oracle oinstall 137 Aug 26 12:15 ora12102_m001_7311.trm
-rw-r----- 1 oracle oinstall 8.6K Aug 26 12:15 ora12102_m001_7311.trc
-rw-r----- 1 oracle oinstall 56 Aug 26 12:16 ora12102_m001_7317.trm
-rw-r----- 1 oracle oinstall 2.2K Aug 26 12:16 ora12102_m001_7317.trc
-rw-r----- 1 oracle oinstall 83 Aug 26 12:17 ora12102_m001_7332.trm
-rw-r----- 1 oracle oinstall 2.2K Aug 26 12:17 ora12102_m001_7332.trc
-rw-r----- 1 oracle oinstall 83 Aug 26 12:18 ora12102_m001_7340.trm
-rw-r----- 1 oracle oinstall 2.2K Aug 26 12:18 ora12102_m001_7340.trc
-rw-r----- 1 oracle oinstall 73 Aug 26 12:19 ora12102_m001_7355.trm
-rw-r----- 1 oracle oinstall 2.2K Aug 26 12:19 ora12102_m001_7355.trc
...
-rw-r----- 1 oracle oinstall 83 Aug 26 12:36 ora12102_m001_7501.trm
-rw-r----- 1 oracle oinstall 2.2K Aug 26 12:36 ora12102_m001_7501.trc
-rw-r----- 1 oracle oinstall 73 Aug 26 12:37 ora12102_m001_7508.trm
-rw-r----- 1 oracle oinstall 2.2K Aug 26 12:37 ora12102_m001_7508.trc
drwxr-x--- 2 oracle oinstall 12K Aug 26 12:37 .
[oracle@db12102 trace]$

3.查看Mxxx的跟踪文件的内容,我们可以看到执行的操作内容。

[oracle@db12102 trace]$ tkprof ora12102_m001_7508.trc ora12102_m001_7508.out
[oracle@db12102 trace]$ cat ora12102_m001_7508.out

Mxxx进程执行的SQL如下(整形后):

SELECT sql_id,
sql_exec_id,
dbop_name,
dbop_exec_id,
To_char(sql_exec_start, 'mm:dd:yyyy hh24:mi:ss'),
To_char(first_refresh_time, 'mm:dd:yyyy hh24:mi:ss'),
To_char(last_refresh_time, 'mm:dd:yyyy hh24:mi:ss'),
elapsed_time,
px_servers_allocated,
sid,
session_serial#,
KEY,
con_id
FROM v$sql_monitor
WHERE report_id = 0
AND status != 'EXECUTING'
AND status != 'QUEUED'
AND px_qcsid IS NULL
AND last_refresh_time >
(SELECT Nvl(last_cycle_time, sysdate - ( 5 / 1440 ))
FROM v$sys_report_stats);

根据上面的内容,我们可以发现,在默认的情况下,MMON_SLAVE后台进程会作以下的工作:

?每隔1分钟检查实时SQL监控信息(v$sql_monitor视图)。
?保存对象为:不是正在执行也也不在排队的 SQL。

4.接着测试,执行监视对象SQL文然后查看跟踪文件中的内容。

SQL> conn teacherwhat/teacherwhat
Connected.
SQL> select/*+ MONITOR */ count(*) from SQLMON where a='A';
COUNT(*)
----------
1000
SQL> SET LINESIZE 1000
col sql_id format a20
col sql_exec_id format a20
col sql_exec_start format a20SQL> SQL> SQL>
SQL> SELECT report_id, key1 sql_id, key2 sql_exec_id, key3 sql_exec_start
FROM dba_hist_reports where key1 ='bq20d7r8f6qa6'; 2
REPORT_ID SQL_ID SQL_EXEC_ID SQL_EXEC_START
---------- -------------------- -------------------- --------------------
20 bq20d7r8f6qa6 16777216 08:25:2016 21:07:26
21 bq20d7r8f6qa6 16777217 08:26:2016 13:10:41 ★

5.查看相关的跟踪文件,我们可以看到,当发现相关的实时SQL监控的信息需要保存到数据库表中时,Oracle会调用sys.dbms_auto_report_internal.i_save_report的程序包把相关信息保存到相关的内部表(WRPREPORTS、WRP_REPORTS_DETAILS)中。

具体动作如下:

BEGIN sys.dbms_auto_report_internal.i_save_report (:rep_ref, :snap_id,
:pr_class, :rep_id, :suc);
END;
INSERT INTO WRP$_REPORTS ...
INSERT INTO WRP$_REPORTS_DETAILS ...
INSERT INTO WRP$_REPORTS_TIME_BANDS ...

其中,wrp$表的更新即反映为如下的相关的视图:

?DBA_HIST_REPORTS ← INT$DBA_HIST_REPORTS ← wrp$_reports
?DBA_HIST_REPORTS_DETAILS ← INT$DBA_HIST_REPORTS_DETAILS ← wrp$_reports_detail

版权声明:本文为博主原创文章,转载必须注明出处,本人保留一切相关权力!http://blog.csdn.net/lukeunique

相关视图和程序包

历史SQL监控的相关视图主要包括以下

DBA_HIST_REPORTS_CONTROL:报告的相关控制信息
DBA_HIST_REPORTS :SQL Monitor、DBOP、Real-Time ADDM等报告的信息
DBA_HIST_REPORTS_DETAILS:各个报告的详细信息

通过DBA_HIST_REPORTS_CONTROL视图的内容我们可以知道,历史SQL监控报告的模式可以分为2种:

REGULAR模式 :根据DB时间预算,每隔一分钟捕获一次
FULL_CAPTURE模式:不考虑DB时间预算,每隔一分钟捕获一次,捕获更多的信息。
/开启FULL_CAPTURE模式
SQL> exec DBMS_AUTO_REPORT.START_REPORT_CAPTURE;
/关闭FULL_CAPTURE模式
SQL> exec DBMS_AUTO_REPORT.FINISH_REPORT_CAPTURE;
参考:
Database Reference 12c
>DBA_HIST_REPORTS_CONTROL
列EXECUTION_MODE:
Mode of execution of automatic report capture. Possible values:
REGULAR: Regular per-minute report capture subject to DBTIME budget
FULL_CAPTURE: Report capture will be run per minute without the DBTIME budget constraints and is provided to capture a more comprehensive set of reports
NOTE: The FULL_CAPTURE mode can be started and ended respectively by executing the START_REPORT_CAPTURE and FINISH_REPORT_CAPTURE APIs in the DBMS_AUTO_REPORT package. At all other times, the execution mode should be REGULAR.
参考:
Database Reference 12c
>DBA_HIST_REPORTS_CONTROL
>DBA_HIST_REPORTS
>DBA_HIST_REPORTS_DETAILS

另外,和这个功能密切相关的程序包DBMS_AUTO_REPORT,也可参考在线文档。

Database PL/SQL Packages and Types Reference
>31 DBMS_AUTO_REPORT
相关参数

我们可以通过下面的方法查看历史SQL监控功能(Historical SQL Monitoring ) 的相关参数。

SQL> set pagesize 100
SQL> set linesize 200
SQL> col Parameter format a40
SQL> col Description format a35
SQL> col Value format a40
SQL> select a.ksppinm "Parameter",a.KSPPDESC "Description",b.ksppstvl "Value"
from x$ksppi a, x$ksppcv b where a.indx = b.indx and a.ksppinm like '%_report_capture%';
2
Parameter Description Value
------------------------------------- ----------------------------------- ---------
_report_capture_cycle_time Time (in sec) between two cycles of 60
report capture daemon
_report_capture_dbtime_percent_cutoff 100X Percent of system db time daem 50
on is allowed over 10 cycles
_report_capture_timeband_length Length of time band (in hours) in t 1
he reports time bands table
_report_capture_recharge_window No of report capture cycles after w 10
hich db time is recharged

另外,在很多案例中由于Bug的影响,MMON进程会因为这个功能而消耗大量的CPU以及内存,或者发生ORA-12850错误(RAC环境)等问题,所以当你遭遇到相关问题时,可以通过设定_report_capture_cycle_time=0来禁用Automatic Report Capturing功能,从而停止历史SQL监控(Historical SQL Monitoring ) 功能来回避相关的问题。

例:
SQL> alter system set "_report_capture_cycle_time"=0;

数据库知识点总结(发展,约束,索引,触发器,连接池,视图,事务)

$
0
0
数据库的发展

数据管理技术的发展经历了以下四个阶段:人工管理阶段、文件系统阶段、数据库阶段和高级数据库技术阶段。

人工管理

50年代中期之前,计算机的软硬件均不完善。硬件存储设备只有磁带、卡片和纸带,软件方面还没有操作系统,当时的计算机主要用于科学计算。这个阶段由于还没有软件系统对数据进行管理,程序员在程序中不仅要规定数据的逻辑结构,还要设计其物理结构,包括存储结构、存取方法、输入输出方式等。

特点:

计算机中没有支持数据管理的软件。数据组织面向应用,数据不能共享,数据重复。在程序中要规定数据的逻辑结构和物理结构,数据与程序不独立。数据处理方式——批处理。
文件系统

这一阶段的主要标志是计算机中有了专门管理数据库的软件——操作系统(文件管理)。

上世纪50年代中期到60年代中期,由于计算机大容量存储设备(如硬盘)的出现,推动了软件技术的发展,而操作系统的出现标志着数据管理步入一个新的阶段。在文件系统阶段,数据以文件为单位存储在外存,且由操作系统统一管理。操作系统为用户使用文件提供了友好界面。文件的逻辑结构与物理结构脱钩,程序和数据分离,使数据与程序有了一定的独立性。用户的程序与数据可分别存放在外存储器上,各个应用程序可以共享一组数据,实现了以文件为单位的数据共享。

但由于数据的组织仍然是面向程序,所以存在大量的数据冗余。而且数据的逻辑结构不能方便地修改和扩充,数据逻辑结构的每一点微小改变都会影响到应用程序。由于文件之间互相独立,因而它们不能反映现实世界中事物之间的联系,操作系统不负责维护文件之间的联系信息。如果文件之间有内容上的联系,那也只能由应用程序去处理。

系统阶段

60年代后,随着计算机在数据管理领域的普遍应用,人们对数据管理技术提出了更高的要求:希望面向企业或部门,以数据为中心组织数据,减少数据的冗余,提供更高的数据共享能力,同时要求程序和数据具有较高的独立性,当数据的逻辑结构改变时,不涉及数据的物理结构,也不影响应用程序,以降低应用程序研制与维护的费用。数据库技术正是在这样一个应用需求的基础上发展起来的。

数据库技术有如下特点:

面向企业或部门,以数据为中心组织数据,形成综合性的数据库,为各应用共享。采用一定的数据模型。数据模型不仅要描述数据本身的特点,而且要描述数据之间的联系。数据冗余小,易修改、易扩充。不同的应用程序根据处理要求,从数据库中获取需要的数据,这样就减少了数据的重复存储,也便于增加新的数据结构,便于维护数据的一致性。程序和数据有较高的独立性。具有良好的用户接口,用户可方便地开发和使用数据库。对数据进行统一管理和控制,提供了数据的安全性、完整性、以及并发控制。
数据库的发展趋势

随着信息管理内容的不断扩展,出现了丰富多样的数据模型(层次模型,网状模型,关系模型,面向对象模型,半结构化模型等),新技术也层出不穷(数据流,Web数据管理,数据挖掘等)。

数据库基本结构

数据库的基本结构分三个层次,反映了观察数据库的三种不同角度。

以内模式为框架所组成的数据库叫做物理数据库;以概念模式为框架所组成的数据叫概念数据库;以外模式为框架所组成的数据库叫用户数据库。

(1)物理数据层。
它是数据库的最内层,是物理存贮设备上实际存储的数据的集合。这些数据是原始数据,是用户加工的对象,由内部模式描述的指令操作处理的位串、字符和字组成。
(2)概念数据层。
它是数据库的中间一层,是数据库的整体逻辑表示。指出了每个数据的逻辑定义及数据间的逻辑联系,是存贮记录的集合。它所涉及的是数据库所有对象的逻辑关系,而不是它们的物理情况,是数据库管理员概念下的数据库。
(3) 用户数据层。
它是用户所看到和使用的数据库,表示了一个或一些特定用户使用的数据集合,即逻辑记录的集合。

数据库不同层次之间的联系是通过映射进行转换的。

数据库特点
(1)实现数据共享
数据共享包含所有用户可同时存取数据库中的数据,也包括用户可以用各种方式通过接口使用数据库,并提供数据共享。
(2)减少数据的冗余度
同文件系统相比,由于数据库实现了数据共享,从而避免了用户各自建立应用文件。减少了大量重复数据,减少了数据冗余,维护了数据的一致性。
(3)数据的独立性
数据的独立性包括逻辑独立性(数据库中数据库的逻辑结构和应用程序相互独立)和物理独立性(数据物理结构的变化不影响数据的逻辑结构)。
(4)数据实现集中控制
文件管理方式中,数据处于一种分散的状态,不同的用户或同一用户在不同处理中其文件之间毫无关系。利用数据库可对数据进行集中控制和管理,并通过数据模型表示各种数据的组织以及数据间的联系。
(5)数据一致性和可维护性,以确保数据的安全性和可靠性
主要包括:①安全性控制:以防止数据丢失、错误更新和越权使用;②完整性控制:保证数据的正确性、有效性和相容性;③并发控制:使在同一时间周期内,允许对数据实现多路存取,又能防止用户之间的不正常交互作用。
(6)故障恢复
由数据库管理系统提供一套方法,可及时发现故障和修复故障,从而防止数据被破坏。数据库系统能尽快恢复数据库系统运行时出现的故障,可能是物理上或是逻辑上的错误。比如对系统的误操作造成的数据错误等。
数据库语言(SQL)

SQL是高级的非过程化编程语言,允许用户在高层数据结构上工作。它不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以具有完全不同底层结构的不同数据库系统可以使用相同的SQL语言作为数据输入与管理的接口。

数据库语言分类

SQL语言包括四类种主要程序设计语言类别的语句:数据定义语言(DDL),数据操作语言(DML)及数据控制语言(DCL)还有事务控制语言(TCL)。

数据定义语言(DDL):表结构定义,表结构更改,例如:CREATE、DROP、ALTER等语句。

数据操作语言(DML):增删改查,例如:INSERT(插入)、UPDATE(修改)、DELETE(删除)语句。

数据查询语言(DQL),例如:SELECT语句。(一般不会单独归于一类,因为只有一个语句)。

数据控制语言(DCL):控制用户对数据库操纵的权限:一、域约束。二、键约束。三、非空约束。四、实体完整性约束。五、参照完整性约束。六、用户定义的完整性,例如:GRANT、REVOKE等语句。

事务控制语言(TCL),例如:COMMIT、ROLLBACK等语句。

标准语句
–数据操作
SELECT --从数据库表中检索数据行和列
INSERT --向数据库表添加新数据行
DELETE --从数据库表中删除数据行
UPDATE --更新数据库表中的数据

增:insert into table(字段1,字段2······) values(int,char,varchar,nvarchar······)

删:delete from table where 字段1=value and|or 字段2=value,truncate table 表名。

改:update table set 字段1=value,字段2=value······ where字段1=value and|or 字段2=value

查:select 字段1,字段2······ from table1 笛卡尔积|on筛选器|添加外部行(left join,right join,inner join) where 字段1=value or|and 字段2=value 字段3 like %string% group by 字段 having 字段>|<|<>value order by desc|asc。

数据定义
CREATE TABLE --创建一个数据库表
DROP TABLE --从数据库中删除表
ALTER TABLE --修改数据库表结构
CREATE VIEW --创建一个视图
DROP VIEW --从数据库中删除视图
CREATE INDEX --为数据库表创建一个索引
DROP INDEX --从数据库中删除索引
CREATE PROCEDURE --创建一个存储过程
DROP PROCEDURE --从数据库中删除存储过程
CREATE TRIGGER --创建一个触发器
DROP TRIGGER --从数据库中删除触发器
CREATE SCHEMA --向数据库添加一个新模式
DROP SCHEMA --从数据库中删除一个模式
CREATE DOMAIN --创建一个数据值域
ALTER DOMAIN --改变域定义
DROP DOMAIN --从数据库中删除一个域
库操作:

一、创建:create database 库名。

二、删除:drop database 库名。

三、更新:alter database 原数据库名称 modify name=新数据库名称。

2、表操作:

一、创建:create table 表名{字段名 类型 约束,······ }

二、删除:drop table 表名。三、更新:alter table oldtable rename to newtable。

3、表结构更改操作:

一、添加字段:alter table 表名 add column 字段 type[(size)] [NOT NULL]。

二、删除字段:alter table 表名 drop column 字段。

三、更改数据类型:alter table 表名 modify 列名 类型。

四、更改字段:alter table 表名 rename column 当前列名 to 新列名。等等。

数据库约束

1、主键约束:primary key

2、唯一约束:unique

3、外键约束:foreign key(涉及级联删除)constraint 外键名 foreign key 当前表列名 references 表名(字段)

4、检查约束:check constraint 约束名 check(表达式)

5、空值约束:NULL/NOT NULL

6、默认约束:default

7、约束操作:

一、删除:drop constraint 约束名。

二、启用:disable constraint 约束名。

三、禁用:enable constraint 约束名。

四、更新:rename constraint 约束名 to 新约束名。

数据库索引

1、索引分类:按存储结构分为聚集索引和非聚集索引,唯一索引。

2、索引的作用:增加数据的查找速度,减少扫描数。(b树)

3、索引创建:create unique|clustered|nonclustered index 索引名 on 表名(column asc|desc)。

4、索引删除:drop index 表名.索引名。

数据库触发器

1、触发器特点:只能通过事件来启动运行,不能直接被调用。

2、触发器作用:数据的维护,数据限制,级联修改等等。

3、触发器结构:

一、触发语句:触发事件update,insert,delete,先后before,after。

二、触发器主体:在触发触发语句时执行SQL语句。

三:触发器限制:通过where 实现

4、触发器语法:create trigger 触发器名 on 表名 for insert|delete|update as begin begin 执行语句 end begin 执行语句 end ······end。

5、触发器操作:
一、禁用:alter table 表名 disable all triggers。

二、启用:alter table 表名 enable all triggers。

三、删除:drop trigger 触发器名。

数据控制
GRANT –授予用户访问权限
DENY –拒绝用户访问
REVOKE –解除用户访问权限
事务控制
COMMIT –结束当前事务
ROLLBACK –回滚当前事务
SET TRANSACTION –定义当前事务数据访问特征
程序化SQL
DECLARE –为查询设定游标
EXPLAN –为查询描述数据访问计划
OPEN –检索查询结果打开一个游标
FETCH –检索一行查询结果
CLOSE –关闭游标
PREPARE –为动态执行准备SQL 语句
EXECUTE –动态地执行SQL 语句
DESCRIBE –描述准备好的查询
数据库的运行机制
数据库执行步骤

一、客户端请求:服务端开辟线程相应用户。

二、用户发起SQL语句查询数据库。

三、查询缓存:记录用户的SQL查询语句,如果挨次查询同样内容,就返回内存。

四、如果缓存没有进入分析器。

五、优化:执行路径的选择,生成执行树。

六、存储引擎:用于管理存储在文件系统。

语法分析器

检测用户命令语法是否正确。原理是将用户的命令进行切片,用空格把多个词分开,获得用户查询的表,内容,权限等。

数据库连接池

一、产生原因:频繁的从硬盘读取数据很慢,所以将数据存在内存中,因此派生出数据库连接池的概念

二、原理:集合、最小连接数、最大连接数、释放时间、最大空闲时间。

数据库事务

1、事务ACID:原子性,一致性,隔离性(数据隔离),持久性。

2、事务隔离级别依据:脏读,不可重复读,幻读。

3、事务分类:显示事务,隐式事务,自动提交事务。

4、事务语法:begin transaction 逻辑语句。

隔离级别 脏读 不可重复读 幻读
读未提交 YES YES YES
读已提交 NO YES YES
可重复读 NO NO YES
串行化 NO NO NO
数据库视图

1、视图的分类:标准视图,索引视图,分区视图

2、视图的作用:

一、集中数据、简化和定制不同用户对数据库的不同数据的要求。

二、屏蔽数据的复杂性。

三、提供用户需求的数据。

四、具有一定的安全机制。

3、创建视图的语句:create view 视图名(列名1,列名2,······) as SQL语句。

4、视图操作:增删改查与数据表几乎一致。

5、视图可以再创建视图。

NoSQL数据库入门概述

$
0
0
关系型数据库与NoSql数据库
什么是NoSQL

Not Only SQL,其含义是:适合关系型数据库的时候就是用关系型数据库,不适用的时候也没必要非得使用关系型数据库不可,可以考虑使用更加合适的数据存储。

为弥补关系型数据库的不足,各种各样的NoSQL数据库运应而生。

数据库的分类

阶层型数据库

早期的数据库称为阶层型数据库,数据的关系都是以简单的树形结构来定义的。程序也通过树形结构对数据进行访问。这种结构,父记录(上层的记录)同时拥有多个子记录(下层记录),子记录只有唯一的父记录。正因为如此,这种非常简单的构造在碰到复杂数据的时候往往会造成数据的重复(同一数据在数据库内重复出现),出现数据冗余的问题。


NoSQL数据库入门概述

阶层型数据库把数据通过阶层结构的方式表现出来,虽然这样的结构有利于提高查询效率,但与此相对应的是,不理解数据结构就无法进行高效的查询。当然,在阶层结构发生变更的时候,程序也需要进行相应的变更。

网络型数据库
前所述,阶层型数据库会带来数据重复的问题。为了解决这个问题,就出现了网络型数据库。它拥有同阶层型数据库相近的数据结构,同时各种数据又如同网状交织在一起,因此而得名。

阶层型数据库只能通过父子关系来表现数据之间的关系。针对这一不足,网络型数据库可以使子记录同时拥有多个父记录,从而解决了数据冗余的问题。


NoSQL数据库入门概述
但是,在网络型数据库中,数据间比较复杂的网络关系使得数据结构的更新变得比较困难。另外,与阶层型数据库一样,网络型数据库对数据结构有很强的依赖性,不理解数据结构就无法进行相应的数据访问。
关系型数据库
最后要向大家介绍的是以科德提出的关系数据模型为基础的关系型数据库。关系型数据库把所有的数据都通过行和列的二元表现形式表示出来,给人更容易理解的直观感受。网络型数据库存在着数据结构变更困难的问题,而关系型数据库可以使多条数据根据值来进行关联,这样就使数据可以独立存在,使得数据结构的变更变得简单易行。
对于阶层型数据库和网络型数据库,如果不理解相应的数据结构,就无法对数据进行读取,它们对数据结构的依赖性很强。因此,它们往往需要专业的工程师使用特定的计算机程序进行操作处理。相反,关系型数据库将作为操作对象的数据和操作方法(数据之间的关联)分离开来,消除了对数据结构的依赖性,让数据和程序的分离成为可能。这使得数据库可以广泛应用于各个不同领域,进一步扩大了数据库的应用范围。
关系型数据库的优势
通用性及高性能
"关系型数据库的性能绝对不低,它具有非常好的通用性和非常高的性能"。毫无疑问,对于绝大多数的应用来说它都是最有效的解决方案。
突出的优势
关系型数据库作为应用广泛的通用型数据库,它的突出优势主要有以下几点:
1、保持数据的一致性(事务处理)
2、由于以标准化为前提,数据更新的开销很小(相同的字段基本上都只有一处)
3、可以进行JOIN等复杂查询
4、存在很多实际成果和专业技术信息(成熟的技术)。
这其中,能够保持数据的一致性是关系型数据库的最大优势。在需要严格保证数据一致性和处理完整性的情况下,用关系型数据库是肯定没有错的。但是有些情况不需要JOIN,对上述关系型数据库的优点也没有什么特别需要,这时似乎也就没有必要拘泥于关系型数据库了。
关系型数据库的不足
不擅长的处理
就像之前提到的那样,关系型数据库的性能非常高。但是它毕竟是一个通用型的数据库,并不能完全适应所有的用途。具体来说它并不擅长以下处理:
1、大量数据的写入处理
2、为有数据更新的表做索引或表结构(schema)变更
3、字段不固定的应用
4、对简单查询需要快速返回结果的处理
大量数据的写入处理

在数据读入方面,由复制产生的主从模式(数据的写入由主数据库负责,数据的读取由从数据库负责),可以比较简单地通过增加从数据库来实现规模化。但是,在数据的写入方面却完全没有简单的方法来解决规模化问题。读写集中在一个数据库上让数据库不堪重负,大部分网站开始使用主从复制技术来实现读写分离,以提高读写性能和读库的可扩展性。

例如,要想将数据的写入规模化,可以考虑把主数据库从一台增加到两台,作为互相关联复制的二元主数据库来使用。确实这样似乎可以把每台主数据库的负荷减少一半,但是更新处理会发生冲突(同样的数据在两台服务器同时更新成其他值),可能会造成数据的不一致。为了避免这样的问题,就需要把对每个表的请求分别分配给合适的主数据库来处理,这就不那么简单了。

下图为两台主机问题:


NoSQL数据库入门概述

另外,也可以考虑把数据库分割开来,分别放在不同的数据库服务器上,比如将这个表放在这个数据库服务器上,那个表放在那个数据库服务器上。数据库分割可以减少每台数据库服务器上的数据量,以便减少硬盘I/O(输入/输出)处理,实现内存上的高速处理,效果非常显著。但是,由于分别存储在不同服务器上的表之间无法进行JOIN处理,数据库分割的时候就需要预先考虑这些问题。数据库分割之后,如果一定要进行JOIN处理,就必须要在程序中进行关联,这是非常困难的。

下图为二元主数据库问题的解决办法:数据库分割


NoSQL数据库入门概述

数据库分割:不能进行JOIN处理


NoSQL数据库入门概述
为有数据更新的表做索引或表结构(schema)变更
在使用关系型数据库时,为了加快查询速度需要创建索引,为了增加必要的字段就一定需要改变表结构。
为了进行这些处理,需要对表进行共享锁定,这期间数据变更(更新、插入、删除等)是无法进行的。如果需要进行一些耗时操作(例如为数据量比较大的表创建索引或者是变更其表结构),就需要特别注意:长时间内数据可能无法进行更新。下表所示为共享锁和排他锁。
NoSQL数据库入门概述
字段不固定的应用

如果字段不固定,利用关系型数据库也是比较困难的。有人会说"需要的时候,加个字段就可以了",这样的方法也不是不可以,但在实际运用中每次都进行反复的表结构变更是非常痛苦的。你也可以预先设定大量的预备字段,但这样的话,时间一长很容易弄不清楚字段和数据的对应状态(即哪个字段保存哪些数据),所以并不推荐使用。下图所示为使用预备字段的情况:


NoSQL数据库入门概述
对简单查询需要快速返回结果的处理
最后还有一点,这点似乎称不上是缺点,但不管怎样,关系型数据库并不擅长对简单的查询快速返回结果。这里所说的"简单"指的是没有复杂的查询条件,而不是用JOIN的意思。因为关系型数据库是使用专门的SQL语言进行数据读取的,它需要对SQL语言进行解析,同时还有对表的锁定和解锁这样的额外开销。这里并不是说关系型数据库的速度太慢,而只是想告诉大家若希望对简单查询进行高速处理,则没有必要非用关系型数据库不可。
在这种情况下,我想推荐大家使用NoSQL数据库。但是像mysql提供了利用HandlerSocket这样的变通方法,也是可行的。虽然使用的是关系型数据库MySQL,但并没有利用SQL而是直接进行数据访问。这样的方法是非常快速的。

下图所示为HandlerSocket的概要:


NoSQL数据库入门概述
NoSQL数据库

上节介绍了关系型数据库的不足之处。为了弥补这些不足(特别是最近几年),NoSQL数据库出现了。关系型数据库应用广泛,能进行事务处理和JOIN等复杂处理。相对地,NoSQL数据库只应用在特定领域,基本上不进行复杂的处理,但它恰恰弥补了之前所列举的关系型数据库的不足之处。

易于数据的分散

如前所述,关系型数据库并不擅长大量数据的写入处理。原本关系型数据库就是以JOIN为前提的,就是说,各个数据之间存在关联是关系型数据库得名的主要原因。为了进行JOIN处理,关系型数据库不得不把数据存储在同一个服务器内(集中),这不利于数据的分散。相反,NoSQL数据库原本就不支持JOIN处理,各个数据都是独立设计的,很容易把数据分散到多个服务器上。由于数据被分散到了多个服务器上,减少了每个服务器上的数据量,即使要进行大量数据的写入操作,处理起来也更加容易。同理,数据的读入操作当然也同样容易。

提升性能和增大规模
下面说一点题外话,如果想要使服务器能够轻松地处理更大量的数据,那么只有两个选择:一是提升性能,二是增大规模。下面我们来整理一下这两者的不同。
首先,提升性能指的就是通过提升现行服务器自身的性能来提高处理能力。这是非常简单的方法,程序方面也不需要进行变更,但需要一些费用。若要购买性能翻倍的服务器,需要花费的资金往往不只是原来的2倍,可能需要多达5~10倍。这种方法虽然简单,但是成本较高。下图所示为提升性能的费用与性能曲线:
NoSQL数据库入门概述
另一方面,增大规模指的是使用多台廉价的服务器来提高处理能力。它需要对程序进行变更,但由于使用廉价的服务器,可以控制成本。另外,以后只要依葫芦画瓢增加廉价服务器的数量就可以了。下图所示为提升性能和增大规模:
NoSQL数据库入门概述
不对大量数据进行处理的话就没有使用的必要吗?
NoSQL数据库基本上来说为了"使大量数据的写入处理更加容易(让增加服务器数量更容易)"而设计的。但如果不是对大量数据进行操作的话,NoSQL数据库的应用就没有意义吗?
答案是否定的。的确,它在处理大量数据方面很有优势。但实际上NoSQL数据库还有各种各样的特点,如果能够恰当地利用这些特点,它就会非常有用。具体的例子将会在第2章和第3章进行介绍,这些用途将会让你感受到利用NoSQL的好处。
1、希望顺畅地对数据进行缓存(Cache)处理
2、希望对数组类型的数据进行高速处理
3、希望进行全部保存
多样的NoSQL数据库

NoSQL数据库存在着"键值存储"、"文档型数据库"、"列存储数据库"等各种各样的种类,每种数据库又包含各自的特点。

NoSQL数据库是什么

NoSQL说起来简单,但实际上到底有多少种呢?我在提笔的时候,到NoSQL的官方网站上确认了一下,竟然已经有122种了。另外官方网站上也介绍了本书没有涉及到的图形数据库和对象数据库等各个类别。不知不觉间,原来已经出现了这么多的NoSQL数据库啊。 本节将为大家介绍具有代表性的NoSQL数据库。


NoSQL数据库入门概述
key-value存储

这是最常见的NoSQL数据库,它的数据是以key-value的形式存储的。虽然它的处理速度非常快,但是基本上只能通过key的完全一致查询获取数据。根据数据的保存方式可以分为临时性、永久性和两者兼具三种。

临时性
memcached属于这种类型。所谓临时性就是 “数据有可能丢失”的意思。memcached把所有数据都保存在内存中,这样保存和读取的速度非常快,但是当memcached停止的时候,数据就不存在了。由于数据保存在内存中,所以无法操作超出内存容量的数据(旧数据会丢失)。
1、在内存中保存数据
2、可以进行非常快速的保存和读取处理
3、 数据有可能丢失
永久性
Tokyo Tyrant、Flare、ROMA等属于这种类型。和临时性相反,所谓永久性就是“数据不会丢失”的意思。这里的key-value存储不像memcached那样在内存中保存数据,而是把数据保存在硬盘上。与memcached在内存中处理数据比起来,由于必然要发生对硬盘的IO操作,所以性能上还是有差距的。但数据不会丢失是它最大的优势。
1、在硬盘上保存数据
2、可以进行非常快速的保存和读取处理(但无法与memcached相比)
3、数据不会丢失
两者兼具
Redis属于这种类型。Redis有些特殊,临时性和永久性兼具,且集合了临时性key-value存储和永久性key-value存储的优点。Redis首先把数据保存到内存中,在满足特定条件(默认是15分钟一次以上,5分钟内10个以上,1分钟内10000个以上的key发生变更)的时候将数据写入到硬盘中。这样既确保了内存中数据的处理速度,又可以通过写入硬盘来保证数据的永久性。这种类型的数据库特别适合于处理数组类型的数据。
1、同时在内存和硬盘上保存数据
2、可以进行非常快速的保存和读取处理
3、保存在硬盘上的数据不会消失(可以恢复)
4、适合于处理数组类型的数据
面向文档的数据库

MongoDB、CouchDB属于这种类型。它们属于NoSQL数据库,但与key-value存储相异。

不定义表结构

面向文档的数据库具有以下特征:即使不定义表结构,也可以像定义了表结构一样使用。关系型数据库在变更表结构时比较费事,而且为了保持一致性还需修改程序。然而NoSQL数据库则可省去这些麻烦(通常程序都是正确的),确实是方便快捷。

可以使用复杂的查询条件
跟key-value存储不同的是,面向文档的数据库可以通过复杂的查询条件来获取数据。虽然不具备事务处理和JOIN这些关系型数据库所具有的处理能力,但除此以外的其他处理基本上都能实现。这是非常容易使用的NoSQL数据库。
1、不需要定义表结构
2、可以利用复杂的查询条件
面向列的数据库

Cassandra、Hbase、HyperTable属于这种类型。由于近年来数据量出现爆发性增长,这种类型的NoSQL数据库尤其引人注目。

面向行的数据库和面向列的数据库

普通的关系型数据库都是以行为单位来存储数据的,擅长进行以行为单位的读入处理,比如特定条件数据的获取。因此,关系型数据库也被称为面向行的数据库。相反,面向列的数据库是以列为单位来存储数据的,擅长以列为单位读入数据。


NoSQL数据库入门概述
高扩展性
面向列的数据库具有高扩展性,即使数据增加也不会降低相应的处理速度(特别是写入速度),所以它主要应用于需要处理大量数据的情况。另外,利用面向列的数据库的优势,把它作为批处理程序的存储器来对大量数据进行更新也是非常有用的。但由于面向列的数据库跟现行数据库存储的思维方式有很大不同,应用起来十分困难。
1、高扩展性(特别是写入处理)
2、应用十分困难
最近,像Twitter和Facebook这样需要对大量数据进行更新和查询的网络服务不断增加,面向列的数据库的优势对其中一些服务是非常有用的,但是由于这与本书所要介绍的内容关系不大,就不进行详细介绍了。
如何导入NoSQL数据库
并非对立而是互补的关系

关系型数据库和NoSQL数据库与其说是对立关系(替代关系),倒不如说是互补关系。笔者认为,与目前应用广泛的关系数据库相对应,在有些情况下使用特定的NoSQL数据库,将会使处理更加简单。

这并不是说“只使用NoSQL数据库”或者“只使用关系型数据库”,而是“通常情况下使用关系型数据库,在适合使用NoSQL的时候使用NoSQL数据库”,即让NoSQL数据库对关系型数据库的不足进行弥补。引入NoSQL数据库时的思维方法:


NoSQL数据库入门概述
量材适用

当然,如果用错的话,可能会发生使用NoSQL数据库反而比使用关系型数据库效果更差的情况。NoSQL数据库只是对关系型数据库不擅长的某些特定处理进行了优化,做到量材适用是非常重要的。

例如,若想获得“更高的处理速度”和“更恰当的数据存储”,那么NoSQL数据库是最佳的选择。但一定不要在关系型数据库擅长的领域使用NoSQL数据库。

增加了数据存储的方式

原来一提到数据存储,就是关系型数据库,别无选择。现在NoSQL数据库给我们提供了另一种选择(当然要根据二者的优点和不足区别使用)。有些情况下,同样的处理若用NoSQL数据库来实现可以变得“更简单、更高速”。而且,NoSQL数据库的种类有很多,它们都拥有各自不同的优势。

在何种程度上依赖它

NoSQL数据库是一门新兴的技术,大家可能会觉得实际的操作经验还不多,还可能碰到新的程序错误,无法放心使用。

实际上,memcached已经相当的成熟了(错误和故障都已经被发现,且有明确的应对方法)。由于有丰富的事例和技术信息,所以不用担心会遇到上述问题。但是,在其他的NoSQL数据库的应用过程中遇到问题的可能性还是存在的。特别是实际应用的时候可以参考的经验、信息太少了。虽然NoSQL数据库能带来很多便利,但是在应用的时候也要考虑这些风险。

反过来说,如果不希望遇到此类问题,还是继续使用关系型数据库吧。它积累了很多成熟经验,更让人放心。

NoSQL数据库的种类和特征
memcached(临时性键值存储)
什么是memcached

memcached是由Danga Interactive公司开发的开源软件,属于临时性键值存储的NoSQL数据库。

为什么使用memcached

高速响应

大多数的Web应用程序通过关系型数据库来保存数据,并从中读取必要的数据显示在用户端浏览器上。当数据量较少时,应用程序可以很快读取结果并显示出来。但当数据量急剧增加,或者需要返回比较复杂的数据合计时,响应时间就会变长,用户也只能被迫等待结果的返回,这样将会降低用户体验。

作为高速缓存使用

那么怎么才能获得高速的响应呢?当然如果是简单处理的话,利用关系型数据库的索引也能获得高速响应。虽然memcached会更加快一些,但如果合理的使用索引,关系型数据库就足够快了。

但是,如果要对多个表的数据进行计算,情况会怎样呢?若使用关系型数据库,我们需要从每个表中取出数据然后进行最后的组合处理,或者每次都要使用JOIN等处理。虽然我们可以通过事前用批处理制作数据来解决这个问题,但是这样又会增加需要管理的表,花费我们更多的精力。

“由于准备数据本身需要关系型数据库花费几十秒到几分钟的时间才能计算出来,因此实时计算就会显得比较慢。”这个时候,memcached就可以大显身手了。因为memcached可以把从关系数据库中读取的数据保存到缓存中,所以即使是需要处理大量数据或者是访问非常集中的情况下,它也能非常快速地返回响应数据。这是因为memcached对于(第二次以后的)相同处理,只要它发现有数据保存在缓存里,就不用通过关系型数据库而直接进行处理。memcached存储的数据有可能丢失,但如果这些数据可以马上重新读取出来的话,那么即使因为memcached停止而导致数据丢失,也不会有什么问题。

特征

memcached是通过大家都很熟悉的散列表(关联数组)来存储各种格式数据的键值存储,所有的数据都被保存在内存中。

memcached利用简单的文本协议来进行数据通信,数据操作也只是类似于保存与键值相对应的值这样的简单处理。因此,通过telnet连接memcached,就可以进行数据的保存和读取。但是,由于它利用的是文本协议,所有无法对构造体类型的数据进行操作,而只能对字符串类型的值进行操作。

当然,通过利用为各种语言准备的程序库来使用memcached的时候,值并不仅仅是字符串和数值,数组和散列表这样的构造体一样可以进行保存和读取处理。但是,如前所述,因为使用了文本协议来进行通信,要完成这样的处理,就必须要把它们转换成序列化的字节数组,通常情况下这些处理是在程序库内部进行的,因此不需要特别在意,但是需要在保存数据的时候进行序列化处理,读取数据的时候进行反序列化处理。

序列化对开发语言的依赖

因为序列化依赖于开发语言,所以某种开发语言环境下进行的序列化结果是无法在其他开发语言环境下使用的。如果要进行这样的处理,就需要通过JSON这样不存在语义依赖关系的格式化方法来进行明确的序列化和反序列化处理。


NoSQL数据库入门概述
优势

说到memcached的优势,要数其极其快速的处理速度。由于数据全部存储在内存中,没有磁盘的IO处理发生,所以它能以比关系数据库高很多的速度进行处理(因为内存中对数据的访问速度是硬盘中的10~100万倍)。

另外一个容易被忽略的优势是她的简单易用性。由于它是通过键值这种散列表形式来操作数据,所以只要用过散列表的人就能很容易的使用它。由于memcached停止的时候所有的数据都会丢失,所以不论遇到什么奇怪的问题,只要重新启动memcached就可以恢复到初始状态。

另外,由于现在很多的Web服务器都在应用memcached,不但拥有了成熟的技术,而且有很多成功经验被公开,这样我们在心里和技术上遇到的困难就会小得多。

随着数据量的增加,当memcached的内存无法保存所有数据的时候,可能就需要多台服务器来进行memcached,实际上通过多台服务器来运行memcached也是非常简单的。在使用多台服务器来运行memcached的时候,会使用一致性散列算法来分散数据。这个算法已经实际应用到memcached的客户端程序库中了。

一致性散列(Consistent Hashing)

如果只是使用多台服务器,就可以利用键的散列值除以服务器台数,通过余数简单地决定哪台服务器处理哪条数据。

但是,这种方法在服务器数量发生变化时就会遇到问题,这时候就需要用到一致性散列这样的分散算法。

这个算法首先对“各个服务器对应的散列值”进行计算,把它们分配到一个圆周上。整个圆周代表键的取值范围,每个服务器承担一个特定取值范围内的键。

四台服务器的一致性散列分配方式:


NoSQL数据库入门概述

新增一台5号服务器时的一致性散列分配方式:


NoSQL数据库入门概述

新增5号服务器后,1、2、3号服务器负责处理的数据没有任何影响,也就是说,对于1、2、3号服务器,服务器数量变化后负责处理的数据与服务器数量变化前负责处理的数据一致,这也是一致性散列中一致性的含义。

但是,原本由4号服务器负责处理的数据,现在由4号服务器和5号服务器共同处理。服务器数量变化后分配给4号服务器处理的数据,之前本来就是由4号服务器处理,只是部分数据被划分给5号服务器负责处理,这样只有一部分数据会受到影响。所谓的一致性散列,并非变化前后服务器的分配保持完全一致。而是将服务器增减带来的缓存错误的影响减小到非常低的水平。

不足

memcached有什么不足之处呢?其实就是大家非常在意的数据临时性(数据有可能丢失)问题。

由于memcached把数据都保存在内存中,当memcached由于故障等原因停止的时候,所有的数据都会丢失。也正因为如此,用它来处理那些重要数据是非常危险的,绝对不要使用。最好的处理方式还是把原始数据保存在其他地方,而只是用memcached来处理原始数据的复制或者是通过原始数据计算出来的结果。

另外,它还存在只能通过键来读取数据这样的局限。不能支持像LIKE这样的模糊查询。


NoSQL数据库入门概述
NoSQL数据库入门概述

memcached的应用

例如:分布式Session


NoSQL数据库入门概述
Tokyo Tyrant

属于NoSQL分类中的永久性键值存储。Tokyo Tyrant和memcached一样,通过键值这样的散列表结构保存数据。但是,数据的保存地点却不一样,memcached是把数据保存在内存中,而Tokyo Tyrant则是把数据保存在磁盘上。

另外,Tokyo Tyrant还引入了数据库类型的概念。可以根据选择的数据库类型,在缓存数据库、散列数据库、B-tree数据库和表数据库等数据保存方式间进行切换。


NoSQL数据库入门概述
优势

由于数据存储在硬盘上,Tokyo Tyrant的最大优势就是在它停止的时候数据也不会丢失。当然,关系数据库也不存在数据丢失的问题,所有从某种程度上说,也算不上什么优势。Tokyo Tyrant的另一个优势是:它在保存和读取数据的时候,与磁盘的IO处理无关,可以实现对数据的高速访问。它可以获得比关系型数据库快得多的处理速度。用户在获得高速反应响应的同时,又不必担心数据丢失的烦恼,真的是非常方便。

关于数据的读取方式,memcached只能通过与键完全一致的条件进行查询,而Tokyo Tyrant存在不同的数据库类型,可以进行范围查询(B-tree数据库)或者像关系型数据库那样进行复杂条件的查询(表格数据库)。同一个产品,能够根据用途的不同而在数据库类型间进行切换实在是方便极了。

不足

虽然既不会发生数据丢失,访问的速度也非常快。但是,使用起来难度大。

Redis(临时性/持久性键值存储)
什么事Redis

它兼具临时性和永久性,所以它是NoSQL数据库中介于memcached和Tokyo Tyrant之间的键值存储。

为什么要使用Redis

处理数组形式的数据

确实,如果要处理字符串数据和标准的散列数据,memcached和Tokyo Tyrant这样的键值存储可能已经足够了。但是,根据用途的不同,也不乏对快速处理数值和数组类型数据的要求

Redis是键值存储的一种,但是它对链表和集合等数组类型的数据进行了优化处理,可以对数组类型的数据进行高速的插入和读取处理,另外,Redis包含很多可以把这些处理原子化的命令,所以可以非常容易的保证数据的一致性。

特征

由于Redis通常是把数据保存在内存中,所以是处理速度非常快的键值存储。虽然已经存在了同样是内存中保存数据的键值存储memcached,但是这两者的用途却大不相同。memcached主要用作关系型数据库的缓存,与关系型数据结合使用,对简单的操作进行优化处理。与之相对,Redis本身就是作为数据存储而设计出来的,它的操作指令非常多,其中很多很多都支持原子操作。

优势

Redis可以处理字符串、链表、集合、有序集合、散列表等各种类型的数据,但需要注意的是所有数据都会被当作字符串处理(数值的保存也是一样)。

由于数据通常保存在内存中,所以处理速度非常快。Redis会定期对数据进行快照处理,除了一部分当前的更新之外,数据都不会丢失。虽然进行数据快照的时候会增加负荷(需要对所有的数据进行IO处理),但是由于数据快照的IO处理通常都是连续IO,所以非常高效。

不足

Redis最大的问题就是这项新技术的使用实例相对较少。

javaee之hibernate的缓存与注解

$
0
0
hibernate的注解:
在项目中,除了有xml的映射配置文件外,还可以在实体类中采用注解的方式来生成映射。
在比较大的项目,通常都是采用xml的映射配置文件,主要是因为在大项目中比较好维护;在小项目中,主要是要求是开发的速率快,大多数就是采用注解的方式来开发
常用的注解:
@Entity:声明一个类是一个映射类 类似:
@Table : 声明一个类映射到的表名 类似:
@Id : 声明一个类的主键类似:
@Column :声明一个类映射表的字段 类似:
@JoinColumn:用来设置外键 类似:
@JoinTable :设置中间表 类似:
@OneToMany :一对多的映射关系
@ManyToMany:多对多的映射关系
@OneToOne :一对一的映射关系
一对多:
User:
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.engine.internal.Cascade;
@Entity
@Table(name="t_user")
public class User {
//主键
@Id
@GeneratedValue //设置id的主键生成策略,generator的属性表示生成策略的类型
@Column(name="id") //生成的字段列,不写name,默认为属性名
private int id;
@Column(name="name")
private String name;
//一对多的关系
/**
* cascade:表示设置级联操作
* mappedBy:表示设置的是维护关联关系,参数值为多方的属性值
*/
@OneToMany(mappedBy="user",cascade={CascadeType.ALL})
//@JoinColumn(name="uid") //当设置了mappedBy的时候,就不能使用JoinColumn或者JoinTable注解
private Set addresses = new HashSet();
public Set getAddresses() {
return addresses;
}
public void setAddresses(Set addresses) {
this.addresses = addresses;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Address:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="t_address")
public class Address {
@Id
@GeneratedValue
@Column(name="id")
private int id;
@Column(name="name")
private String name;
@Column(name="phone")
private String phone;
@Column(name="addre")
private String addre;
//表示的多对一
@ManyToOne
@JoinColumn(name="uid")
private User user ;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddre() {
return addre;
}
public void setAddre(String addre) {
this.addre = addre;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
多对多:
Course:
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
/**
* @author Mao
*
*/
@Entity
@Table(name="t_course")
public class Course {
@Id
@GeneratedValue
@Column(name="id")
private int id;
@Column(name="name")
private String name;
@ManyToMany(mappedBy="course")
private Set student = new HashSet();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getStudent() {
return student;
}
public void setStudent(Set student) {
this.student = student;
}
}
Student:
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@Entity
@Table(name="t_student")
public class Student {
@Id
@GeneratedValue
@Column(name="id")
private int id;
@Column(name="name")
private String name;
//表示多对多关系
@ManyToMany(cascade={CascadeType.ALL})
//设置中间表
@JoinTable(name="student_course",joinColumns=@JoinColumn(name="sid"),inverseJoinColumns=@JoinColumn(name="cid"))
private Set course = new HashSet();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getCourse() {
return course;
}
public void setCourse(Set course) {
this.course = course;
}
}
一对一:
Person:
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name="t_person")
public class Person {
@Id
@GeneratedValue
@Column(name="id")
private int id;
@Column(name="name")
private String name;
@OneToOne(mappedBy="person",cascade={CascadeType.ALL})
private IdCard idcard;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public IdCard getIdcard() {
return idcard;
}
public void setIdcard(IdCard idcard) {
this.idcard = idcard;
}
}
IdCard:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name="t_idcard")
public class IdCard {
@Id
@GeneratedValue
@Column(name="id")
private int id;
@Column(name="cardno")
private String cardno;
@OneToOne
@JoinColumn(name="pid",unique=true)
private Person person;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCardno() {
return cardno;
}
public void setCardno(String cardno) {
this.cardno = cardno;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
测试类:
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import util.HibernateUtils;
public class text {
@Test
public void test01(){
Session session = HibernateUtils.getSession();
Transaction tx = session.getTransaction();
tx.begin();
User u = new User();
u.setName("狗剩");
Address a1 = new Address();
a1.setName("狗剩的老婆");
a1.setAddre("广州天河");
Address a2 = new Address();
a2.setName("狗剩的妈妈");
a2.setAddre("广州番禺");
u.getAddresses().add(a1);
u.getAddresses().add(a2);
a1.setUser(u);
a2.setUser(u);
session.save(u);
tx.commit();
HibernateUtils.close(session);
}
@Test
public void test02(){
Session session = HibernateUtils.getSession();
Transaction tx = session.getTransaction();
tx.begin();
Student s1 = new Student();
s1.setName("张三");
Student s2 = new Student();
s2.setName("李四");
Course c1 = new Course();
c1.setName("jsp开发");
Course c2 = new Course();
c2.setName("struts2框架");
s1.getCourse().add(c1);
s1.getCourse().add(c2);
c1.getStudent().add(s1);
c2.getStudent().add(s1);
s2.getCourse().add(c1);
c1.getStudent().add(s2);
session.save(s1);
session.save(s2);
tx.commit();
HibernateUtils.close(session);
}
@Test
public void test03(){
Session session = HibernateUtils.getSession();
Transaction tx = session.getTransaction();
tx.begin();
Person p = new Person();
p.setName("张三");
IdCard ic = new IdCard();
ic.setCardno("4422223333");
p.setIdcard(ic);
ic.setPerson(p);
session.save(p);
tx.commit();
HibernateUtils.close(session);
}
}
hibernate的懒加载:
当要查询数据的时候,hibernate会先去一级缓存和二级缓存中查询,如果没有查询到数据的时候,这个时候才会去数据库查询。
采用懒加载的机制后,查询到的数据不会一次性全部查询到,而是到了需要用到的数据才会去查询该数据
Address:
public class Address {
private int id;
private String name;
private String phone;
private String address;
private User user;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
User:
import java.util.HashSet;
import java.util.Set;
public class User {
private int id;
private String name;
private Set addresses = new HashSet();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getAddresses() {
return addresses;
}
public void setAddresses(Set addresses) {
this.addresses = addresses;
}
}
Address.hbm.xml
User.hbm.xml
测试类:
/**
*
//延迟加载
/**
* 1) 类的延迟加载
* get(): 不支持类的延迟加载
* load(): 支持类的延迟加载
*
* 2) 类的关联关系延迟加载
* lazy="false"
* @author APPle
*/
public class App {
@Test
public void test01(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
/**
* 一个对象的延迟加载:get和load方法区别
* get方法都是立即加载的,没有延迟加载的效果
* load方法是支持延迟加载的
*
* 2、当在映射文件中设置lazy为false,则表示不懒加载,默认为true
*/
User u = (User)session.load(User.class, 1); //现在查询到只是User的对象地址,不包含其他属性
System.out.println(u.getName()); //这个时候需要得到user的name,所有才继续去查询,但是这是只有name这个属性,没有其他属性
System.out.println(u.getAddresses()); //这个时候又再去查询user的address属性
User u1 = (User)session.get(User.class, 1);//现在查询到User对象,包括User里面的全部属性
System.out.println(u.getName()); //这个时候可以直接取到来使用
System.out.println(u.getAddresses());
tx.commit();
HibernateUtils.close(session);
}
hibernate的缓存:
1、关于hibernate的缓存机制,是为了提供hibernate框架运行的性能,尽量减少和数据库的连接次数。其中包括hibernate的一级缓存、hibernate的二级缓存
hibernate一级缓存:
为Session级别的缓存,是属于事务缓存,所有缓存数据都放在session对象,当session关闭的时候就会丢失缓存数据
Student:
public class Student {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Student.hbm.xml
测试类:
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import util.HibernateUtils;
public class App {
//演示一级缓存
@Test
public void test01(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
//第一次查询过的数据会放在一级缓存中,并且使用id来标记
Student s1 =(Student) session.get(Student.class, 1);
Student s2 =(Student) session.get(Student.class, 1);
System.out.println(s1=s2); //true
tx.commit();
HibernateUtils.close(session);
}
//修改也是走一级缓存
@Test
public void test02(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
/*Student s = (Student)session.get(Student.class, 1); // s对已经放到了一级缓存
//修改
s.setName("李四");//修改一级缓存中的数据
*/
/*int i =1;
for(Student s: list){
if(i%1000==0){
//同步数据
session.flush();
//清空一级缓存的数据
session.clear();
}
session.save(s);
}*/
Student s1 = (Student)session.get(Student.class, 1);
Student s2 = (Student)session.get(Student.class, 1);
session.evict(s1);
//session.clear();
Student s3 = (Student)session.get(Student.class, 1);
tx.commit(); //commit()方法在提交事务之前,会调用session.flush()方法来同步一级缓存和数据库的数据
HibernateUtils.close(session);
}
//演示hibernate不同对象状态的转换
@Test
public void test03(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
Student s = new Student(); //s是处于临时状态
s.setName("xx"); //不会对数据库进行任何的操作
session.save(s); //s是处于持久化状态
session.evict(s); //s是处于游离态
session.delete(s); //s是处于删除态
tx.commit();
HibernateUtils.close(session);
}
}
hibernate二级缓存:
为SessionFactory级别的缓存,是属于进程缓存,所有缓存数据都放在SessionFactory,所有二级缓存的数据不会随着session对象的关闭而丢失
javaee之hibernate的缓存与注解
测试类:
//演示二级缓存,同时需要在cfg.xml中进行配置
@Test
public void test2(){
Session session1 = HibernateUtils.getSession();
Transaction tx = session1.getTransaction();
tx.begin();
Address a1 = (Address)session1.get(Address.class, 1);
tx.commit();
HibernateUtils.close(session1);
Session session2 = HibernateUtils.getSession();
Transaction tx2 = session2.getTransaction();
tx2.begin();
Address a2 = (Address)session2.get(Address.class, 1);
tx2.commit();
HibernateUtils.close(session2);
}
hibernate.cfg.xml
org.hibernate.c3p0.internal.C3P0ConnectionProvider20103000trueorg.hibernate.cache.ehcache.EhCacheRegionFactory
2、hibernate的对象状态
①临时态:
没有在数据库中有任何的记录,普通的为刚创建出来的对象数据
特点:
1、没有OID(对象的主键值)
2、数据库中没有对应的记录
3、任何的修改操作的不会反映到数据库
4、临时对象不在一级缓存
②持久态:
保存数据在数据库中,并且在一级缓存中
特点:
1、有OID(对象的主键值)
2、数据库中有对应的记录
3、任何的修改操作的会反映到数据库
4、持久化对象在一级缓存
③游离态:
把对象在一级缓存中清除
特点:
1、有OID(对象的主键值)
2、数据库中有对应的记录
3、任何的修改操作的不会反映到数据库
4、游离对象不在一级缓存
④删除态:
把对象进行删除,或者变成垃圾回收
特点:
1、有OID(对象的主键值)
2、数据库中没有对应的记录
3、任何的修改操作的不会反映到数据库

4、删除对象不在一级缓存


javaee之hibernate的缓存与注解

MongoDB学习(五)使用Java驱动程序3.3操作MongoDB快速入门

$
0
0
【引言】

毕竟现在MongoDB还是出于成长阶段,所以现在网上相关的资料很少,而且大部分还都是针对于MongoDB的老版本的。再加上MongoDB的频繁升级、重大更新等等,导致菜鸟学习的难度增大。

好了,前几篇讲的都是MongoDB数据库相关的知识,最终,还是要与java来接轨(当然,卤煮是搞java开发的)。看了看现在的java驱动版本截至目前2016年8月27日为止为3.3,与网上搜索到的教程很多写法不一致,所以卤煮在此决定研究一下官网的教程,希望能对自己或者其他人有一点帮助,足矣...

ps:本文只是官网的一个快速入门,让我这样的菜鸟能了解个大概,有些地方可能还需要深入的学习才能读懂。本人水平有限,有些地方有删减,翻译不到位的地方还请各位看官海涵并留言指出,本人一定虚心学习改正,以免误导!

【翻译篇】

官网原文地址:戳这里

MongoDB驱动程序快速入门
以下的所有示例代码来自QuickTour.java文件,可以在驱动程序源代码中找到。
1.创建一个连接
下面的例子展示了通过5种方式来连接本地的数据库 mydb,如果数据库不存在,MongoDB会自动创建。
// 简单直接的连接数据库,默认为本机地址localhost,端口号27017
MongoClient mongoClient = new MongoClient();
// 或者像这样指定连接地址
MongoClient mongoClient = new MongoClient( "localhost" );
// 或者像这样指定连接地址和端口号
MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
// 或者像这样连接到一个副本集,需要提供一个列表
MongoClient mongoClient = new MongoClient(
Arrays.asList(new ServerAddress("localhost", 27017),
new ServerAddress("localhost", 27018),
new ServerAddress("localhost", 27019)));
// 或者使用连接字符串
MongoClientURI connectionString = new MongoClientURI("mongodb://localhost:27017,localhost:27018,localhost:27019");
MongoClient mongoClient = new MongoClient(connectionString);
// 获取到数据库对象mydb,如果不存在则自动创建
MongoDatabase database = mongoClient.getDatabase("mydb");
MongoClient 一个MongoClient实例实际上表示的是一个数据库连接池,即使是多线程,你也只需要一个MongoClient类的实例。
注意

通常,对于一个数据库集群你仅仅只需要创建一个MongoClient实例,并且使用它来贯穿你的整个应用程序。当创建多个实例的时候:

注意每个MongoClient实例的所有资源使用限制(最大连接数等等)销毁实例,请确保你调用MongoClient.close() 来清理资源
2.获取一个集合
要获取一个集合来进行更多操作,需要为getCollection()方法指定一个集合的名称。下面的例子表示获取名称为 test 的集合:
MongoCollection collection = database.getCollection("test");
3.插入一个文档
一旦你有了Collection集合对象了,你可以往集合中插入一个文档。例如,观察下面的JSON文档,这个文档中又包含了一个嵌入式的文档字段 info
{
"name" : "MongoDB",
"type" : "database",
"count" : 1,
"info" : {
x : 203,
y : 102
}
}
使用java驱动程序中的Document类来创建文档,你同样也可以使用这个类来创建嵌入式的文档。
Document doc = new Document("name", "MongoDB")
.append("type", "database")
.append("count", 1)
.append("info", new Document("x", 203).append("y", 102));
使用insertOne()方法来向集合中插入文档
collection.insertOne(doc);
4.插入多个文档
你可以使用insertMany()方法来插入多个文档。下面的例子将会创建多个文档:
{ "i" : value }
在一个循环中创建文档:
List documents = new ArrayList();
for (int i = 0; i < 100; i++) {
documents.add(new Document("i", i));
}
把这些文档插入到集合中,把这个文档列表传递给insertMany()方法:
collection.insertMany(documents);
5.统计集合中的文档数量
到现在为止我们已经插入了101个文档(我们在循环中创建了100个,加上第一个文档),我们可以使用count()方法来检查一下它们是否都已经插入成功了。下面的代码应该输出101:
System.out.println(collection.count());
6.查询集合
使用find()方法来查询集合。
6.1查询集合中的第一个文档
要获取集合中的第一个文档,需要在find()方法操作后调用first()方法,collection.find().first() 返回第一个文档或者空,而不是一个游标。这对于只需要匹配单个文档或者你只需要第一个文档的查询很有用处。下面的例子会打印出从集合中找到的第一个文档:
Document myDoc = collection.find().first();
System.out.println(myDoc.toJson());
这个例子将会输出以下内容:
{ "_id" : { "$oid" : "551582c558c7b4fbacf16735" },
"name" : "MongoDB", "type" : "database", "count" : 1,
"info" : { "x" : 203, "y" : 102 } }
注意

_id字段是由MongoDB自动添加到文档中的,从而与其他的文档进行区分展示。MongoDB保留所有以“_”、“$”为开始的字段名,以供内部使用。

6.2查询集合中的所有文档
要检索集合中的所有文档,需要使用find()方法。该方法返回了一个提供灵活接口的FindIterable实例来控制查询操作。使用iterator()方法可以得到一个匹配查询条件的文档集迭代器。下面的代码检索了集合中的所有文档,并且把它们输出来(101个文档)
MongoCursor cursor = collection.find().iterator();
try {
while (cursor.hasNext()) {
System.out.println(cursor.next().toJson());
}
} finally {
cursor.close();
}
虽然下面的语句是允许的,但是不鼓励使用,因为如果循环提前终止的话可能会遗漏一个游标。
for (Document cur : collection.find()) {
System.out.println(cur.toJson());
}
7.使用查询过滤器得到一个单一的文档
我们可以创建一个过滤器并传递给find()方法,来得到集合中文档的子集。例如,我们想要查询字段“i”的值为71的文档,我们可以这样做:
import static com.mongodb.client.model.Filters.*;
myDoc = collection.find(eq("i", 71)).first();
System.out.println(myDoc.toJson());
然后它就会仅仅输出一个文档:
{ "_id" : { "$oid" : "5515836e58c7b4fbc756320b" }, "i" : 71 }
注意

可以使用 Filters, Sorts, Projections 和Updates类来创建简单明了的查询方式。

8.查询一组文档
我们可以使用查询来获得集合中的一组文档。例如,如果我们想得到 i>50 的文档,我们可以这样写:
// 现在使用范围查询来得到一个大点的子集
Block printBlock = new Block() {
@Override
public void apply(final Document document) {
System.out.println(document.toJson());
}
};
collection.find(gt("i", 50)).forEach(printBlock);
请注意,在这里我们在FindIterable 上面使用了forEach()方法,并且打印出了所有 i>50的文档。我们还可以得到一个范围,比如说,50collection.find(and(gt("i", 50), lte("i", 100))).forEach(printBlock);
9.排序
我们也可以使用Sorts帮助类来进行排序文档。我们通过在FindIterable 上调用sort()方法来添加一个排序查询,下面我们使用exists()方法和descending("i")方法来排序:
myDoc = collection.find(exists("i")).sort(descending("i")).first();
System.out.println(myDoc.toJson());
exists():查询含有指定字段的文档 descending():按照某一字段进行desc降序排序,同理还有ascending()方法
10.字段投影
有时候我们并不需要文档中的所有数据,Projections帮助类可以帮助我们在查询操作中创建投影参数。下面我们将进行整理,通过使用Projections.execludeId()方法来排除文档中的“_id”字段,并且输出第一个匹配的文档:
myDoc = collection.find().projection(excludeId()).first();
System.out.println(myDoc.toJson());
11.聚合
有时候,我们需要聚合存储在MongoDB中的数据,Aggregates 帮助类为每种类型的聚合提供了构建。下面我们将通过一个简单的两步骤转换,来计算 i*10的值。首先我们使用Aggregates.match()方法来查询所有i>0的文档,然后我们使用Agreegates.project()方法重塑文档,再结合$multiply操作来计算“ITimes10”的值:
collection.aggregate(asList(
match(gt("i", 0)),
project(Document.parse("{ITimes10: {$multiply: ['$i', 10]}}")))
).forEach(printBlock);
12.更新文档
使用updateOne()方法来更新0个或1个文档(如果没有和过滤器匹配的话则是0个),并且要指定过滤器和更新后的文档。这里我们使用Updates.set()方法来更新符合i=10的第一个文档,并且设置i的值为110:
collection.updateOne(eq("i", 10), set("i", 110));
要更新所有匹配过滤器的文档,需要使用updateMany()方法。这里我们使用Updates.inc()方法来对i<100的文档进行增加100(即i+100):
UpdateResult updateResult = collection.updateMany(lt("i", 100), inc("i", 100));
System.out.println(updateResult.getModifiedCount());
更新方法返回一个UpdateResult对象,该对象提供了包括更新文档的数量等信息。
13.删除文档
使用deleteOne()方法来删除0个或1个文档
collection.deleteOne(eq("i", 110));
使用deleteMany()方法来删除匹配过滤的所有文档。这里我们删除i>=100的所有文档:
DeleteResult deleteResult = collection.deleteMany(gte("i", 100));
System.out.println(deleteResult.getDeletedCount());
删除方法返回一个DeleteResult对象,该对象中提供了包括删除文档数量等信息。
14.批量操作
这些新命令允许批量插入/更新/删除操作的执行,这里有两种批量操作的方式(不知道理解的对不对
MongoDB学习(五)使用Java驱动程序3.3操作MongoDB快速入门
):

有序批量操作。

执行所有预定操作,当出现写入错误时会停止操作。

无序批量操作。

执行所有操作,并报告所有的错误。

无序批量操作不保证所有操作的执行。

// 2. 有序批量操作,调用是有保证的 collection.bulkWrite( Arrays.asList(new InsertOneModel<>(new Document("_id", 4)), new InsertOneModel<>(new Document("_id", 5)), new InsertOneModel<>(new Document("_id", 6)), new UpdateOneModel<>(new Document("_id", 1), new Document("$set", new Document("x", 2))), new DeleteOneModel<>(new Document("_id", 2)), new ReplaceOneModel<>(new Document("_id", 3), new Document("_id", 3).append("x", 4)))); // 2. 无序批量操作,调用没有保证 collection.bulkWrite( Arrays.asList(new InsertOneModel<>(new Document("_id", 4)), new InsertOneModel<>(new Document("_id", 5)), new InsertOneModel<>(new Document("_id", 6)), new UpdateOneModel<>(new Document("_id", 1), new Document("$set", new Document("x", 2))), new DeleteOneModel<>(new Document("_id", 2)), new ReplaceOneModel<>(new Document("_id", 3), new Document("_id", 3).append("x", 4))), new BulkWriteOptions().ordered(false));
重要

当MongoDB的服务器版本为2.6以下时,不推荐使用bulkWrite方法,因为这是第一个支持批量插入、更新、删除命令的服务器版本,在某种程度上,可以让驱动程序实现BulkWriteResult和BulkWriteException的正确的语义。该方法仍然会在2.6以下版本的服务器工作,但性能将受到影响,因为每个写操作将会被单独执行一次。

Web数据库SQL命令,数据库创建_增删改查_表与表之间的关联

$
0
0

1)创建数据库

create database mytest1;

2)删除数据库

drop database mytest1;

3)创建表

create table stu(StudyNo int primary key auto_increment,

IdCarNo int,

Name char(10),

Sex char(10),

Elective char(10));

4)创建一对一表(两个表关联,副表的主键必须是主表的外键才可以。)

create table country(id int primary key auto_increment,

Name char(10),

Language char(10));

create table President(id int primary key auto_increment,

Name char(10),

sex char,

f_country_id);

alter table President add constraint foreign key(f_country_id) references country(id) on delete cascade;

//该语句红色前面部分是将附表中的外键与主表中的外键相关联,红色部分表示删除主表中的记录会影响到删除副表中的相应数据,删除副表中数据不会影响主表中的相应数据。

5)创建一对多表

create table class(id int primary key auto_increment,

classname char(10),

HederTeacher char(10));

create table stu(id int primary key auto_increment,

name char(10),

age int,

f_class_id);

alter table stu add constraint foreign key(f_class_id) references class(id) on delete set null;

//红色部分表示删除主表的主键后,副表相关联的部分用null表示。删除副表不会影响主表。

6)创建多对多表

create table teacher_stu_middle(id int primary key auto_increment,

f_Teacher_id int,

f_Stu_id );

create table Teacher(id int primary key auto_increment,

name char(10));

create table Stu(id int primary key auto_increment,

name char(10));

alter table teacher_stu_middle add constraint foreign key(f_Teacher_id)references Teacher(id) on delete no action;

alter table teacher_stu_middle add constraint foreign key(f_Stu_id)references Stu(id) on delete no action;

//红色部分表示主表不能删除与附表有任何关联的记录,可以删掉附表中的任意记录。

7)字段约束

主键字约束:primary key

外键字约束:foreign key

唯一性约束:unique

非空约束:not null

检查约束:check(mysql数据库对该约束不起作用)

缺省约束:default

8)数值类型

int、float、double

字符串类型:char(只能存储一个字符)

char(M)(能存储M个字符)(优点:效率高,缺点:占用内存多)

varchar(M)(根据内容决定,但不超过M)(优点:占用内存少,缺点:效率低)

9)数据库增加条目

insert into stu(id,name,sex,age)values(13,’小李’,’男’,20);//根据添加的顺序依次添加

insert into stu values(14,’小李’,’男’,34);//必须把所有字段都添加

10)数据库删除条目

delete from stu where id=2;

delete from stu where id=2 and sex=’女’;//and表示都满足的意思

delete from stu where id=2 or sex = ‘男’;//or表示满足其中之一都可以

delete from stu where id in(25,26);//in表示删除id=25或者26

delete from stu where id not in(25,26)//not in 表示删除除了id=25或者26的其它记录。

删除字段1的那条记录

Delete from 表名 where 字段1=值1;

删除字段1并且字段2=值2的那条记录

Delete form 表名 where 字段1=值1and 字段2=值2;

删除字段1=值2或者字段1=值3的两条记录

Delete form 表名where 字段1= 值2 or 字段1= 值3;

删除字段1=值1以及字段1=值3的两条记录

Delete from 表名 where 字段1 in(值1,值3);

删除id不等于1、2、3的记录;

Delete from 表名 where id not in(1,2,3);

删除id>35的所有记录,不包括35

Delete from 表名 where id>35;

删除id>30并且id<34的记录,不包括30、34

Delete from 表名 where id>30 and id<34;

删除id<2或者id>35的所有记录,不包括2、35

Delete from 表名 where id<2 or id>35;

11)数据库修改条目

update stu set sex=’男’where age>10 and age<20;

update stu set sex=’男’,name=’小李’where id=’2’;//修改多个用逗号分隔

将sex=’m’的全部记录修改为’男’

Update 表名 set sex=’男’where sex=’m’;

将id=30那条记录的sex改为‘女’

Update 表名 set sex=’女’where id=30;

将id=29那条记录的cardno改为‘2016’,name改为‘(●’?’●)’

Update 表名 set cardno=‘2016’,name=‘(●’?’●)’where id=29;

查询数据

查询表里的所有数据

Select * from 表名;

查询student表中id>20的所有记录的数据

Select * from studentwhere id>20;

查询表中所有字段2的信息

Select 字段2 from 表名;

查询表中字段2,字段4,字段6的信息

Select 字段2,字段4,字段6 from 表名;

查询id<10的name,sex,elective的字段信息

Select name,sex,elective from 表名 where id<10;

多表查询语句

1、 查询各班的学生信息:笛卡儿积

方式1:

selectt_class.C_NAME,t-stu.S_NAME,t_stu_S_SEX,t_stu.S_MONEY

from t_class,t_stu;

方式2:

selectc.C_NAME,s.S_NAME,s.S_SEX,s.S_MONEY

from t_class c,s_stu s

2、 查询各班的学生信息,当t_stu表中的C_ID等于t_class表中的C_ID时,表示该班级的学生

selectc.C_NAME,s.S_NAME,s.S_SEX,s.S_MONEY

from t_class c,t_stu s

where c.C_ID=s.C_ID

3、 查询班级名称、学生姓名、性别、缴费、相同班级的要放在一起,姓名根据字典顺序排列。

selectc.C_NAME,s.S_NAME,s,s.S_SEX,s.S_MONEY

from t_class c,t_stu s

where c.C_ID=s.C_ID

order by c.C_ID,s.S_ID

4、 查询各班的班级名称和人数(通过班级名称进行分组查询)

select c.C_NAME,count(*)as 人数

from t_class c,s_stu s

where s.C_ID=c.C_ID

group by c.C_ID

查询各班名称和人数,但人数必须小于2,人数多的放在前面

注:group by 用于分组,

Having用于分组后进行条件过滤,

Order by用于选取相应的字段进行排序,

desc表示倒序

查询没有人员的班级

注:distinct表示返回表中不同记录的条数,就是返回不同记录的字段值

select *from t_class c

wherec.C_ID not in(select distinct s.C_ID from t_stu s where s.S_ID>3);

等价于: select * from t_class c where c.C_ID not in(21);

分组查询语句:

根据name字段进行分组查询,并统计每一组的人数

selectcount(*) from student group by name;

根据name字段查询,并得到每一个组的人数

selectname,count(*)as 人数 from student group by name;

根据name字段查询,并得到每一组的人数以及每一组中id的最大值

selectname,count(*) as 人数, max(id) from student group byname;

根据sex字段进行查询,并统计每一组的人数

select sex,count(*)as 人数,min(id) from student group by sex;

根据sex进行分组查询,并只对id等于3、28、30的3条记录进行分组查询

selectsex,count(*)from student where id in(3,28,30) group by sex;

根据sex进行分组查询,并只对id>20的所有记录进行分组查询

select sex,count(*)from student where id>20 group by sex desc;

面试总结(数据库范式、sql优化)

$
0
0

数据库范式

为了建立冗余较小、结构合理的数据库,设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。范式是符合某一种设计要求的总结。要想设计一个结构合理的关系型数据库,必须满足一定的范式。

1、第一范式(确保每列保持原子性)

第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。

第一范式的合理遵循需要根据系统的实际需求来定。比如某些数据库系统中需要用到“地址”这个属性,本来直接将“地址”属性设计成一个数据库表的字段就行。但是如果系统经常会访问“地址”属性中的“城市”部分,那么就非要将“地址”这个属性重新拆分为省份、城市、详细地址等多个部分进行存储,这样在对地址中某一部分操作的时候将非常方便。这样设计才算满足了数据库的第一范式,如下表所示。

2、第二范式(确保表中的每列都和主键相关)

第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。

比如要设计一个订单信息表,因为订单中可能会有多种商品,所以要将订单编号和商品编号作为数据库表的联合主键,如下表所示。

这个表中是以订单编号和商品编号作为联合主键。这样在该表中商品名称、单位、商品价格等信息不与该表的主键相关,而仅仅是与商品编号相关。所以在这里违反了第二范式的设计原则。

而如果把这个订单信息表进行拆分,把商品信息分离到另一个表中,把订单项目表也分离到另一个表中,就非常完美了。

3、第三范式(确保每列都和主键列直接相关,而不是间接相关)

第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。

比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。如下面这两个表所示的设计就是一个满足第三范式的数据库表。

这样在查询订单信息的时候,就可以使用客户编号来引用客户信息表中的记录,也不必在订单信息表中多次输入客户信息的内容,减小了数据冗余。

4.Sql优化

a.索引问题

在做性能跟踪分析过程中,经常发现有不少后台程序的性能问题是因为缺少合适索引造成的,有些表甚至一个索引都没有。这种情况往往都是因为在设计表时,没去定义索引,而开发初期,由于表记录很少,索引创建与否,可能对性能没啥影响,开发人员因此也未多加重视。然一旦程序发布到生产环境,随着时间的推移,表记录越来越多

这时缺少索引,对性能的影响便会越来越大了。

这个问题需要数据库设计人员和开发人员共同关注

法则:不要在建立的索引的数据列上进行下列操作:

◆避免对索引字段进行计算操作

◆避免在索引字段上使用not,<>,!=

◆避免在索引列上使用IS NULL和IS NOT NULL

◆避免在索引列上出现数据类型转换

◆避免在索引字段上使用函数

◆避免建立索引的列中使用空值。

b.复杂操作

部分UPDATE、SELECT 语句 写得很复杂(经常嵌套多级子查询)——可以考虑适当拆成几步,先生成一些临时数据表,再进行关联操作。

c.在可以使用UNION ALL的语句里,使用了UNION

UNION 因为会将各查询子集的记录做比较,故比起UNION ALL ,通常速度都会慢上许多。一般来说,如果使用UNION ALL能满足要求的话,务必使用UNION ALL。还有一种情况大家可能会忽略掉,就是虽然要求几个子集的并集需要过滤掉重复记录,但由于脚本的特殊性,不可能存在重复记录,这时便应该使用UNION ALL,如xx模块的某个查询程序就曾经存在这种情况,见,由于语句的特殊性,在这个脚本中几个子集的记录绝对不可能重复,故可以改用UNION ALL)

d.where语句

d.1 避免在WHERE子句中使用in,not in,or 或者having。

可以使用 exist 和not exist代替 in和not in。

可以使用表链接代替 exist。Having可以用where代替

d.2 不要以字符格式声明数字,要以数字格式声明字符值。(日期同样)否则会使索引无效,产生全表扫描。

e.对Select语句的法则

在应用程序、包和过程中限制使用select * from table这种方式。

f. 排序

避免使用耗费资源的操作,带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 执行,耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序。

g.临时表

慎重使用临时表可以极大的提高系统性能

Spring Data MongoDB + JSR-310 or Java 8 new Date APIs

$
0
0

While saving an object containing the new Java 8 java.time.LocalDateTime , the following error is thrown :

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.time.LocalDateTime] to type [java.util.Date]

Tested

Spring 4.3.2.RELEASE Spring Data MongoDB 1.9.2.RELEASE

Is Spring-data supporting the new Java 8 Date APIs (JSR-310)?

1. Spring Data + JSR-310

Yes, Spring-data supports the JSR-310 spec, with a custom convertor Jsr310Converters , review the following code snippet :

CustomConversions.java

package org.springframework.data.mongodb.core.convert; public class CustomConversions { /** * Creates a new {@link CustomConversions} instance registering the given converters. * * @param converters */ public CustomConversions(List<?> converters) { //... List<Object> toRegister = new ArrayList<Object>(); // Add user provided converters to make sure they can override the defaults toRegister.addAll(converters); toRegister.add(CustomToStringConverter.INSTANCE); toRegister.addAll(MongoConverters.getConvertersToRegister()); toRegister.addAll(JodaTimeConverters.getConvertersToRegister()); toRegister.addAll(GeoConverters.getConvertersToRegister()); toRegister.addAll(Jsr310Converters.getConvertersToRegister()); toRegister.addAll(ThreeTenBackPortConverters.getConvertersToRegister()); for (Object c : toRegister) { registerConversion(c); } //... } 2. Solution

The above Jsr310Converters will be enabled if you declared a Spring managed bean for MappingMongoConverter , and pass as an argument for MongoTemplate , review the following MongoConfig example :

MongoConfig.java

//... import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @Configuration @ComponentScan(basePackages = {"com.mkyong.db"}) public class MongoConfig { //... @Autowired MongoDbFactory mongoDbFactory; @Bean public MongoTemplate mongoTemplate() throws Exception { MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, getDefaultMongoConverter()); return mongoTemplate; } @Bean public MappingMongoConverter getDefaultMongoConverter() throws Exception { MappingMongoConverter converter = new MappingMongoConverter( new DefaultDbRefResolver(mongoDbFactory), new MongoMappingContext()); return converter; } //... }

The MappingMongoConverter extends AbstractMongoConverter , and the AbstractMongoConverter is an InitializingBean . If this declared as a Spring managed bean via @Bean , the afterPropertiesSet() will be fired, and registered all the default convertors, including the Jsr310Converters

3. FAQs

If the MappingMongoConverter is not managed by Spring (init with a new keyword like below), you must call the .afterPropertiesSet() manually.

MongoConfig.java

@Configuration @ComponentScan(basePackages = {"com.mkyong.db"}) public class MongoConfig { @Autowired MongoDbFactory mongoDbFactory; @Bean public MongoTemplate mongoTemplate() throws Exception { MappingMongoConverter converter = new MappingMongoConverter( new DefaultDbRefResolver(mongoDbFactory), new MongoMappingContext()); //CALL THIS MANULLY, so that all the default convertors will be registered! converter.afterPropertiesSet(); MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, converter); return mongoTemplate; } //... References Github Custom converters to spring-data-mongodb Spring IO MappingMongoConverter JavaDoc Spring IO CustomConversions JavaDoc

Voron’s internals: MVCC - All the moving parts

$
0
0

Voron’s internals: MVCC - All the moving parts

I talked about the different aspects of building a database engine in detail in the past month or so. But I tried to talk about each topic independently, so it will make sense. The problem is that in the real world, there are actually quite a lot of related stuff that impact on one another. This series of posts is meant to tie everything together, so you’ll have a better understanding how the design decisions in one place being affected by the requirement in somewhere that seems utterly unrelated.

Before we can talk about the implementation details, let us see what we are trying to achieve. Voron is:

High performance. Single write, multiple readers (MVCC) Fully ACID

In this post, I’m not going to talk about the data model, or how we sort it, or anything like that. No, we are at a much lower level than that. We are at how we access the raw data pages and manage them.

There are actually multiple players involved here. We have the journal for durability of writes, we have the data file to store the data, the scratch file to implement Multi Versioning Concurrency Control and the Page Translation Tables to provide snapshot isolation for concurrent transactions.

The design of Voron is immensely simplified by the fact that we choose to go with a single writer model. We share this design decision with other databases engines such as LMDB, LevelDB, RocksDB, etc. Concurrent write transactions are much more complex and require a lot more effort, and you still have the serialization at the journal level, although I explored multiple ways around it. With Voron, we decided to go with a single write transaction for the simplicity, and then implementedtransaction merging on top of that, which give us a tremendous performance boost in high load scenarios.

But let us talk about MVCC. The idea is that we have concurrent versions of the data, so each transaction has a snapshot of the entire database and can operate on that without fear of write transactions modifying data while it is running. Let us explore how this works when the database starts.

The key to that is the notion of the page translation table, from now on, known as the PTT. When the database starts, we have an empty PTT, and the data file itself. We open a read transaction, which has the following data:

ReadTx-1:

PTT: [ /* no entries */ Data file

Whenever the read transaction need to read a page, it consults the PTT, find that there is nothing there, and read the page from the data file. We keep the read transaction open, and open a new write transaction. It also gets a PTT and the data file, but it also needs to keep track of a few other things:

WriteTx-2:

PTT: [/* no entries */] Data file Dirty pages

Now, we want to make a change to the database, which happens to fall on Page #3. Here we have problem, we can’t modify the data file directly, ReadTx-1 is still running, and it might want to read the data in Page #3 at some point. Instead of modifying the data directly, we copy the page into the scratch file.

The scratch file is just a temporary file that we use to store data copies. After we copy the data, we update the PTT. Now when we search for Page #3, we’ll find the location of the page in the scratch file. As far as the write transaction is concerned, this doesn’t matter. A page is a page is a page, and it doesn’t matter where it is at.

Committing the transaction means taking all of the dirty pages in the write transaction and writing them to the log. After which we atomically set the PTT for the write transaction as the global PTT. Now, all future read transactions will have the new PTT and when they will ask for Page #3, they will get the page from the scratch file.

A new write transaction that needs to (again) modify Page #3, will create another copy of the Page inside the scratch file.This ends up looking like this:


Voron’s internals: MVCC - All the moving parts

We have three copies of Page #3. One for the original read transaction (in the data file), one for the current read transactions (yellow in the scratch file) and the current modified page (orange in the scratch file) that we are writing to.

When the write transaction completes, we again flush the dirty pages to the journal and then publish our PTT so all future transactions can see the changes.

Of course, that is just one side of it, in my next post, I’ll discuss how we clear the scratch file and move data back to the data file.

Viewing all 6262 articles
Browse latest View live