精华内容
下载资源
问答
  • 相信大家在写论文或者改投的过程中总会遇到根据不同的期刊需要调整参考文献【格式】的情况,如果一个一个手输、手改的话会及其麻烦。 甚至有些格式非百度学术或者谷歌学术引用所生成的格式,该怎么生成我们目标刊物...

    如果解决了你的问题,撒泼打滚求赞~~

    在写论文或者改投的过程中总会遇到根据不同的期刊需要调整参考文献【格式】的情况,如果一个一个手输、手改的话会及其麻烦。遇到的坑,怎么爬过来的,总结如下:

    甚至有些格式非百度学术或者谷歌学术引用所生成的格式,该怎么生成我们目标刊物的格式呢?

    比如我们要生成一个下面这样的奇葩格式。是不是跟你平时百度、google直接引用的长得不太像?手打可能想原地去世!!!

    那怎么办呢?使用文献管理软件Zetero,自动批量生成参考文献,从此,删除、改投都不怕~

    刚开始使用Zetero的效果可能是这样的:

    奇奇怪怪的插入效果

    是不是很气,为什么别人用着就那么顺手,自己用着就这么难受呢?

    是因为使用的步骤出了一些问题鸭~

    不急不急,往下看

    那正确使用Zetero插入参考文献的步骤是什么呢?

    1.打开zetero软件

    2.打开所要插入文献的文档

    3.设置参考文献引用格式,需保证本机zetero软件是开启的,否则会报错。

    4.将鼠标点在需要添加参考文献的位置,点击Add/Edit citation。

    5.添加引用参考文献的具体信息

     

    具体具体的操作如下哦~

    1.打开zetero软件

    2.打开所要插入文献的文档

    3.设置参考文献引用格式,需保证本机zetero软件是开启的,否则会报错。

    (这一步及其重要!!!!不执行这一步,直接执行插入操作的话,会导致插入文献的引文格式和引文标签格式都是默认的,会导致文献插出来是这样一种奇奇怪怪的效果,让人及其难受。)

    在word选项栏选择Zetero选项卡下的Document preferences 

    在引文样式中选择相应的格式

    4.将鼠标点在需要添加参考文献的位置,点击Add/Edit citation。

    在弹出的输入栏中可以选择【保持源分类】和【经典视图】两种选项。

        ①保持原分类

    保持原分类在输入字母后有联想功能,但是可能很多时候我们我们记不太清每一个的具体名字是什么,因为学术文章的名字真的是差不多。

        ②经典视图

    5.在需要显示引用内容的部分,通常是Reference的后面选择Add/Edit Bibliography,就可以得到相应的参考文献引用。

    就生成相应的参考文献了,如下图:

    后续只需要进行第四步引用操作,插件会自动生成引文项。

    那有些小宝贝要问了,我怎么才能知道我要插入的是那种格式呢?该怎么找到呢?请看下篇嘛

    如果解决了你的问题的话,请给小白晏点赞哦,  你的鼓励是我努力总结的动力鸭

    正需要攒钱喝奶茶的小白晏期待您的打赏,一毛两毛,一块两块都可,哈哈哈,比心心~~

    展开全文
  • 当你执行新增或update动作然后rollback后,之前格式话的空间会继续保留 无论事务有多大,事务响应时间都是很平(时间差不错一样) 在jdbc连接中,如果想让速度变快必须做到减少硬解析 减少软解析 ...
    redo重做信息是oracle在在线重做日志文件中记录的信息,万一出现失败可以利用这些数据来重做事务
    undo是oracle在undo段中记录的信息,用于取消或回滚事务。

    当你执行新增或update动作然后rollback后,之前格式话的空间会继续保留

    无论事务有多大,事务的响应时间都是很平的(时间差不错一样)

    在jdbc连接中,如果想让速度变快必须做到减少硬解析 减少软解析 游标重用,尽量少的commit
    比如:

    ps = conn.prepareStatement("delete T_DEV_NEWSEVENTS where id=?");
    for(int i=0;i<10000;i++)
    {
    System.out.println(i);
    //ps = conn.prepareStatement("insert into T_DEV_NEWSEVENTS values(?,?,?,?,?)");
    ps.setString(1,i+"");
    ps.setString(2,"");
    ps.setDate(3,(java.sql.Date) new Date(Calendar.getInstance().getTimeInMillis()));
    ps.setDate(4,(java.sql.Date) new Date(Calendar.getInstance().getTimeInMillis()));
    ps.setInt(5, 1);
    //ps.setString(1, i+"");
    ps.execute();
    }
    conn.commit();
    这段部分能执行很好,但是如果把prepareStatement放在for里面,那么不能游标重用,如果把prepareStatement改成Statement,那么每次将硬解析,如果把commit放在for里面,那么性能肯定低很多,如果还想速度更快,可以使用ps.addBath()和ps.exeuteBatch()批处理


    在数据库执行commit之前,困难的工作都己经做了,我们已经修改了数据库中的数据,所以99.9%的工作都己经完成,例如,已经发生了以下操作:
    1.已经在SGA中生成了undo快
    2.已经在SGA中生成了已修改数据块
    3.已经在SGA中生成了对于前两项的缓存redo
    4.取决与前三项的大小,以及这些工作花费的时间,前面的每个数据可能已经刷新输出到磁盘
    5.已经得到了所需的全部锁
    执行commit时,余下的工作只是:
    1.为事务生成一个SCN
    2.LGWR将所有余下的缓存重做日志条目写到磁盘,并把SCN记录到在线重做日志文件中。这一步就是真正的commit
    3.V$LOCK中记录我们的会话持有的锁,这些所有都被释放,而排队等待这些锁的没一个人都会被唤醒,可以继续完成他们的工作。
    4.如果事务修改的某些快还在缓冲区缓存中,则会以一种快速的模式访问并“清理”


    rollback时,要做以下工作:
    1.撤销已做的所有修改,其完成方式如下:从undo段读回数据,然后实际上逆向执行前面所做的操作,并将undo条目标记为已用
    2.会话持有的所有锁都将释放,如果有人在排队等待我们持有的锁,将会被唤醒

    结论:rollback的花费远远超过commit的花费,rollback的花费直接跟之前执行的操作有关,所以尽量的少rollback


    通常对undo有一个误解,认为undo用于数据库物理地恢复到执行语句或事务之前的样子,但实际上并非如此。数据库只是逻辑地恢复到原来的样子,所有修改都被逻辑地取消,但是数据结构以及数据库块本身在回滚后可能大不相同。原因在于:在所有多用户系统中,可能会有数十、数百甚至数千个并发事务。数据库的主要功能之一就是协调对数据的并发访问。也许我们的事务在修改一些块,而一般来讲往往会有许多其他的事务也在修改这些块。因此,不能简单地将一个块放回到我们的事务开始前的样子,这样会撤销其他人(其他事务)的工作!



    9.3 redo和undo如何协作?

    有意思的是,尽管undo信息存储在undo表空间或undo段中,但也会受到redo的保护。换句话说,会把undo数据当成是表数据或索引数据一样,对undo的修改会生成一些redo,这些redo将计入日志。为什么会这样呢?稍后在讨论系统崩溃时发生的情况时将会解释它,到时你会明白了。将undo数据增加到undo段中,并像其他部分的数据一样在缓冲区缓存中得到缓存。另外这些redo信息还用于在实例恢复时重建SGA内存的状态。



    9.3.1 COMMIT做什么?

    COMMIT通常是一个非常快的操作,而不论事务大小如何。你可能认为,一个事务越大(换句话说,它影响的数据越多),COMMIT需要的时间就越长。不是这样的。不论事务有多大,COMMIT的响应时间一般都很“平”(flat,可以理解为无高低变化)。这是因为COMMIT并没有太多的工作去做,不过它所做的确实至关重要。

    这一点很重要,之所以要了解并掌握这个事实,原因之一是:这样你就能心无芥蒂地让事务有足够的大小。一种错误的信念认为分批提交可以节省稀有的系统资源,而实际上这只是增加了资源的使用。如果只在必要时才提交(即逻辑工作单元结束时),不仅能提高性能,还能减少对共享资源的竞争(日志文件、各种内部闩等)。

    分批提交COMMIT的开销存在两个因素:

    l 显然会增加与数据库的往返通信。如果每个记录都提交,生成的往返通信量就会大得多。

    l 每次提交时,必须等待redo写至磁盘。这会导致“等待”。在这种情况下,等待称为“日志文件同步”(log file sync)。



    为什么COMMIT的响应时间相当“平”,而不论事务大小呢?在数据库中执行COMMIT之前,困难的工作都已经做了。我们已经修改了数据库中的数据,所以99.9%的工作都已经完成。例如,已经发生了以下操作:

    l 已经在SGA中生成了undo块。

    l 已经在SGA中生成了已修改数据块。

    l 已经在SGA中生成了对于前两项的缓存redo。

    l 取决于前三项的大小,以及这些工作花费的时间,前面的每个数据(或某些数据)可能已经刷新输出到磁盘。

    l 已经得到了所需的全部锁。

    执行COMMIT时,余下的工作只是:

    l 为事务生成一个SCN。如果你还不熟悉SCN,起码要知道,SCN是Oracle使用的一种简单的计时机制,用于保证事务的顺序,并支持失败恢复。SCN还用于保证数据库中的读一致性和检查点。可以把SCN看作一个钟摆,每次有人COMMIT时,SCN都会增1.

    l LGWR将所有余下的缓存重做日志条目写到磁盘,并把SCN记录到在线重做日志文件中。这一步就是真正的COMMIT。如果出现了这一步,即已经提交。事务条目会从V$TRANSACTION中“删除”,这说明我们已经提交。

    l V$LOCK中记录这我们的会话持有的锁,这些所都将被释放,而排队等待这些锁的每一个人都会被唤醒,可以继续完成他们的工作。

    l 如果事务修改的某些块还在缓冲区缓存中,则会以一种快速的模式访问并“清理”。块清除(Block cleanout)是指清除存储在数据库块首部的与锁相关的信息。实质上讲,我们在清除块上的事务信息,这样下一个访问这个块的人就不用再这么做了。我们采用一种无需生成重做日志信息的方式来完成块清除,这样可以省去以后的大量工作(在下面的“块清除”一节中将更全面地讨论这个问题)。



    可以看到,处理COMMIT所要做的工作很少。其中耗时最长的操作要算LGWR执行的活动(一般是这样),因为这些磁盘写是物理磁盘I/O。不过,这里LGWR花费的时间并不会太多,之所以能大幅减少这个操作的时间,原因是LGWR一直在以连续的方式刷新输出重做日志缓冲区的内容。在你工作期间,LGWR并非缓存这你做的所有工作;实际上,随着你的工作的进行,LGWR会在后台增量式地刷新输出重做日志缓冲区的内容。这样做是为了避免COMMIT等待很长时间来一次性刷新输出所有的redo。

    因此,即使我们有一个长时间运行的事务,但在提交之前,它生成的许多缓存重做日志已经刷新输出到磁盘了(而不是全部等到提交时才刷新输出)。这也有不好的一面,COMMIT时,我们必须等待,直到尚未写出的所有缓存redo都已经安全写到磁盘上才行。也就是说,对LGWR的调用是一个同步(synchronous)调用。尽管LGWR本身可以使用异步I/O并行地写至日志文件,但是我们的事务会一直等待LGWR完成所有写操作,并收到数据都已在磁盘上的确认才会返回。

    前面我提高过,由于某种原因,我们用的是一个Java程序而不是PL/SQL,这个原因就是PL/SQL提供了提交时优化(commit-time optimization)。我说过,LGWR是一个同步调用,我们要等待它完成所有写操作。在Oracle 10g Release 1及以前版本中,除PL/SQL以外的所有编程语言都是如此。PL/SQL引擎不同,要认识到直到PL/SQL例程完成之前,客户并不知道这个PL/SQL例程中是否发生了COMMIT,所以PL/SQL引擎完成的是异步提交。它不会等待LGWR完成;相反,PL/SQL引擎会从COMMIT调用立即返回。不过,等到PL/SQL例程完成,我们从数据库返回客户时,PL/SQL例程则要等待LGWR完成所有尚未完成的COMMIT。因此,如果在PL/SQL中提交了100次,然后返回客户,会发现由于存在这种优化,你只会等待LGWR一次,而不是100次。这是不是说可以在PL/SQL中频繁地提交呢?这是一个很好或者不错的主意吗?不是,绝对不是,在PL/SQ;中频繁地提交与在其他语言中这样做同样糟糕。指导原则是,应该在逻辑工作单元完成时才提交,而不要在此之前草率地提交。

    COMMIT是一个“响应时间很平”的操作,虽然不同的操作将生成不同大小的redo,即使大小相差很大或者说无论生成多少redo,但也并不会影响提交(COMMIT)的时间或者说提交所用的时间都基本相同。



    9.3.2 ROLLBACK做什么?

    一般地回滚时间是所修改数据量的一个函数。回滚操作的开销很大,这是可以想像的,因为ROLLBACK必须物理地撤销我们所做的工作。类似于COMMIT,必须完成一系列操作。在到达ROLLBACK之前,数据库已经做了大量的工作。再复习一遍,可能已经发生的操作如下:

    l 已经在SGA中生成了undo块。

    l 已经在SGA中生成了已修改数据块。

    l 已经在SGA中生成了对于前两项的缓存redo。

    l 取决于前三项的大小,以及这些工作花费的时间,前面的每个数据(或某些数据)可能已经刷新输出到磁盘。

    l 已经得到了所需的全部锁。



    ROLLBACK时,要做以下工作:

    l 撤销已做的所有修改。其完成方式如下:从undo段读回数据,然后实际上逆向执行前面所做的操作,并将undo条目标记为已用。如果先前插入了一行,ROLLBACK会将其删除。如果更新了一行,回滚就会取消更新。如果删除了一行,回滚将把它再次插入。

    l 会话持有的所有锁都将释放,如果有人在排队等待我们持有的锁,就会被唤醒。



    1.4 分析redo

    作为一名开发人员,应该能够测量你的操作生成了多少redo,这往往很重要。生成的redo越多,你的操作花费的时间就越长,整个系统也会越慢。你不光在影响你自己的会话,还会影响每一个会话。redo管理是数据库中的一个串行点。任何Oracle实例都只有一个LGWR,最终所有事务都会归于LGWR,要求这个进程管理它们的redo,并BOMMIT其事务,LGWR要做的越多,系统就会越慢。



    9.4.1 测量redo

    要查看生成的redo量相当简单,这在本章前面已经见过。我使用了SQL*Plus的内置特性AUTOTRACE。不过AUTOTRACE只能用于简单的DML,对其他操作就力所不能及了,例如,它无法查看一个存储过程调用做了什么。为此,我们需要访问两个动态性能视图:

    l V$MYSTAT,其中有会话的提交信息。

    l V$STATNAME,这个视图能告诉我们V$MYSTAT中的每一行表示什么(所查看的统计名)。



    9.4.2 redo生成和BEFORE/AFTER触发器

    l BEFORE或AFTER触发器不影响DELETE生成的redo。

    l 在Oracle9i Release 2 及以前版本中,BEFORE或AFTER触发器会使INSERT生成同样数量的额外redo。在Oracle 10g中,则不会生成任何额外的redo。

    l 在Oracle9i Release 2及以前的所有版本中,UPDATE生成的redo只受BEFORE触发器的影响。AFTER触发器不会增加任何额外的redo。不过,在Oracle 10g中,情况又有所变化。具体表现为:

    Ø 总的来讲,如果一个表没有触发器,对其更新期间生成的redo量总是比Oracle9i及以前版本中要少。看来这是Oracle着力解决的一个关键问题:对于触发器的表,要减少这种表更新所生成的redo量。

    Ø 在Oracle 10g中,如果表有一个BEFORE触发器,则其更新期间生成的redo量比9i中更大。

    Ø 如果表有AFTER触发器,则更新所生成的redo量与9i中一样。



    在Oracle9i Release 2和Oracle 10g这两个版本之间,触发器对事务实际生成的redo存在不同的影响。可以很容易地看到这些变化:

    l 是否存在触发器对DELETE没有影响(DELETE还是不受触发器的影响)。

    l 在Oracle9i Release 2及以前版本中,INSERT会受到触发器的影响。初看上去,你可能会说,Oracle 10g优化了INSERT,所以它不会受到影响,但是再看看Oracle 10g中无触发器时生成的redo总量,你会看到,这与Oracle9i Release 2及以前版本中有触发器时生成的redo量是一样的。所以,并不是Oracle 10g减少了有触发器时INSERT生成的redo量,而是所生成的redo量是常量(有无触发器都会生成同样多的redo),无触发器时,Oracle 10g中的INSERT比Oracle9i中生成的redo要多。

    l 在9i中,UPDATE会受BEFORE触发器的影响,但不受AFTER触发器的影响。初看上去,似乎Oracle 10g中改成了两个触发器都会影响UPDATE。但是通过进一步的分析,可以看到,实际上Oracle 10g中无触发器是UPDATE生成的redo有所下降,下降的量正是有触发器时UPDATE生成的redo量。所用与9i和10g中INSERT的情况恰恰相反,与9i相比,没有触发器时Oracle 10g中UPDATE生成的redo量会下降。



    触发器对redo生成的影响

    DML操作
    AFTER触发器(10g以前)
    BEFORE触发器(10g以前)
    AFTER触发器(10g)
    BEFORE触发器(10g)

    DELETE
    不影响
    不影响
    不影响
    不影响

    INSERT
    增加redo
    增加redo
    常量redo
    常量redo

    UPDATE
    增加redo
    不影响
    增加redo
    增加redo




    现在你应该知道怎么来估计redo量,这是每一个开发人员应该具备的能力。你可以:

    l 估计你的“事务”大小(你要修改多少数据)。

    l 在要修改的数据量基础上再加10%~20%的开销,具体增加多大的开销取决于你要修改的行数。修改行越多,增加的开销就越小。

    l 对于UPDATE,要把这个估计值加倍。



    9.4.3 我能关掉重做日志生成吗?

    答案很简单:不能。因为重做日志对于数据库至关重要;它不是开销,不是浪费。



    1. 在SQL中设置NOLOGGING

    有些SQL语句和操作支持使用NOLOGGING子句。这并不是说:这个对象的所有操作在执行时都不生成重做日志,而是说有些特定操作生成的redo会比平常(即不使用NOLOGGING子句时)少得多。

    在NOARCHIVELOG模式的数据库中,除了数据字典的修改外,CREATE TABLE不会记录日志。(为什么?CREATE TABLE难道不是数据字典操作?)如果你想在NOARCHIVELOG模式的数据库上看到差别,可以把对表T的DROP TABLE和CREATE TABLE换成DROP INDEX和CREATE INDEX。默认情况下,不论数据库以何种模式运行,这些操作都会生成日志。



    关于NOLOGGING操作,需要注意以下几点:

    l 事实上,还是会生成一定数量的redo。这些redo的作用是保护数据字典。这是不可避免的。与以前(不使用NOLOGGING)相比,尽管生成的redo量要少多了,但是确实会有一些redo。

    l NOLOGGING不能避免所有后续操作生成redo。在前面的例子中,我创建的并非不生成日志的表。只是创建表(CREATE TABLE)这一个操作没有生成日志。所有后续的“正常“操作(如INSERT、UPDATE和DELETE)还是会生成日志。其他特殊的操作(如使用SQL*Loader的直接路径加载,或使用INSERT /*+ APPEND */语法的直接路径插入)不生成日志(除非你ALTER这个表,再次启用完全的日志模式)。不过,一般来说,应用对这个表执行的操作都会生成日志。

    l 在一个ARCHIVELOG模式的数据库上执行NOLOGGING操作后,必须尽快为受影响的数据文件建立一个新的基准备份,从而避免由于介质失败而丢失对这些对象的后续修改。实际上,我们并不会丢失后来做出的修改,因为这些修改确实在重做日志中;我们真正丢失的只是要应用这些修改的数据(即最初的数据)。



    2.在索引上设置NOLOGGING

    使用NOLOGGING选项有两种方法。你已经看到了前一种,也就是把NOLOGGING关键字潜在SQL命令中。另一种方法是在段(索引或表)上设置NOLOGGING属性,从而隐式地采用NOLOGGING模式来执行操作。

    如alter一个索引:

    ops$tkyte@ORA10G> alter index t_idx rebuild;

    Index altered.

    以后rebuild的时候只会生成少许日志,而不会生成大量的额外的日志。但是,现在这个索引没有得到保护(unprotected),如果它所在的数据文件失败而必须从一个备份恢复,我们就会丢失这个索引数据。了解这一点很重要。现在索引是不可恢复的,所以需要做一个备份。或者,DBA也可以干脆创建索引,因为完全可以从表数据直接创建索引。



    3. NOLOGGING小结

    可以采用NOLOGGING模式执行以下操作:

    l 索引的创建和ALTER(重建)。

    l 表的批量INSERT(通过/*+APPEND */提示使用“直接路径插入“。或采用SQL*Loader直接路径加载)。表数据不生成redo,但是所有索引修改会生成redo,但是所有索引修改会生成redo(尽管表不生成日志,但这个表上的索引却会生成redo!)。

    l LOB操作(对大对象的更新不必生成日志)。

    l 通过CREATE TABLE AS SELECT创建表。

    l 各种ALTER TABLE操作,如MOVE和SPLIT。

    在一个ARCHIVELOG模式的数据库上,如果NOLOGGING使用得当,可以加快许多操作的速度,因为它能显著减少生成的重做日志量。



    9.4.4 为什么不能分配一个新日志?

    老是有人问我这个问题。这样做会得到一条警告消息(可以在服务器上的alert.log中看到):

    Thread 1 cannot allocate new log, sequence 1466

    Checkpoint not complete

    Current log# 3 seq# 1465 mem# 0: /home/ora10g/oradata/ora10g/redo03.log

    警告消息中也可能指出Archival required而不是Checkpoint not complete,但是效果几乎都一样。DBA必须当心这种情况。如果数据库试图重用一个在线重做日志文件,但是发现做不到,就会把这样一条消息写到服务器上的alert.log中。如果DBWR还没有完成重做日志所保护数据的检查点(checkpointing),或者ARCH还没有把重做日志文件复制到归档目标,就会发生这种情况。对最终用户来说,这个时间点上数据库实际上停止了。它会原

    地不动。DBWR或ARCH将得到最大的优先级以将redo块刷新输出的磁盘。完成了检查点或归档之后,一切又回归正常。

    如果你看到会话因为一个“日志文件切换”、“日志缓冲区空间”或“日志文件切换检查点或归档未完成”等待了很长时间,就很可能遇到了这个问题。

    要解决这个问题,有几种做法:



    l 让DBWR更快一些。让你的DBA对DBWR调优,为此可以启用ASYNC I/O、使用DBWR I/O从属进程,或者使用多个DBWR进程。看看系统产生的I/O,查看是否有一个磁盘(或一组磁盘)“太热”,相应地需要将数据散布开。这个建议对ARCH也适用。这种做法的好处是,你不用付出什么代价就能有所收获,性能会提高,而且不必修改任何逻辑/结构/代码。这种方法确实没有缺点。

    l 增加更多重做日志文件。在某些情况下,这会延迟Checkpoint not complete的出现,而且过一段时间后,可以把Checkpoint not complete延迟得足够长,使得这个错误可能根本不会出现(因为你给DBWR留出了足够的活动空间来建立检查点)。这个方法也同样适用于Archival required消息。这种方法的好处是可以消除系统中的“暂停”。其缺点是会消耗更多的磁盘空间,但是在此利远远大于弊。

    l 重新创建更大的日志文件。这会扩大填写在线重做日志与重用这个在线重做日志文件之间的时间间隔。如果重做日志文件的使用呈“喷射状”,这种方法同样适用于Archival required消息。倘若一段时间内会大量生成日志(如每晚加载、批处理等),其后一段数据却相当平静,如果有更大的在线重做日志,就能让ARCH在平静的期间有足够的时间“赶上来”。这种方法的优缺点与前面增加更多文件的方法是一样的。另外,它可能会延迟检查点的发生,由于(至少)每个日志切换都会发生检查点,而现在日志切换间隔会更大。

    l 让检查点发生得更频繁、更连续。可以使用一个更小的块缓冲区缓存(不太好),或者使用诸如FAST_START_MTTR_TARGET、LOG_CHECKPOINT_INTERVAL和LOG_CHECKPOINT_TIMEOUT之类的参数设置。这会强制DBWR更频繁地刷新输出脏块。这种方法的好处是,失败恢复的时间会减少。在线重做日志中应用的工作肯定更少。其缺点是,如果经常修改块,可能会更频繁地写至磁盘。缓冲区缓存本该更有效的,但由于频繁地写磁盘,会导致缓冲区缓存不能充分发挥作用,这可能会影响下一节将讨论的块清除机制。



    9.4.5 块清除

    在第6章中,我们曾经讨论过数据锁以及如何管理它们。我介绍了数据锁实际上是数据的属性,存储在块首部。这就带来一个副作用,下一次访问这个块时,可能必须“清理”这个块,换句话说,要将这些事务信息删除。这个动作会生成redo,并导致变脏(原本并不脏,因为数据本身没有修改),这说明一个简单的SELECT有可能生成redo,而且可能导致完成下一个检查点时将大量的块写至磁盘。不过,在大多数正常的情况下,这是不会发生的。如果系统中主要是小型或中型事务(OLTP),或者数据仓库会执行直接路径加载或使用DBMS_STATS在加载操作后分析表,你会发现块通常已经得到“清理”。如果还记得前面“COMMIT做什么?”一节中介绍的内容,应该知道,COMMIT时处理的步骤之一是:如果块还在SGA中,就要再次访问这些块,如果可以访问(没有别人在修改这些块),则对这些块完成清理。这个 活动称为提交清除(commit cleanout),即清除已修改块上事务信息。最理想的是,COMMIT可以完成块清除,这样后面的SELECT(读)就不必再清理了。只有块的UPDATE才会真正清除残余的事务信息,由于UPDATE已经在生成redo,所用注意不到这个清除工作。

    可以强制清除不发生来观察它的副作用,并了解提交清除是怎么工作的。在与我们的事务相关的提交列表中,Oracle会记录已修改的块列表。这些列表都有20个块,Oracle会根据需要分配多个这样的列表,直至达到某个临界点。如果我们修改的块加起来超过了块缓冲区缓存大小的10%,Oracle会停止为我们分配新的列表。例如,如果缓冲区缓存设置为可以缓存3,000个块,Oracle会为我们维护最多300个块(3,000的10%)。COMMIT时,Oracle会处理这些包含20个块指针的列表,如果块仍可用,它会执行一个很快的清理。所以,只要我们修改的块数没有超过缓存中总块数的10%,而且块仍在缓存中并且是可用的,Oracle就会在COMMIT时清理这些块。否则,它只会将其忽略(也就是说不清理)。

    如果你有如下的处理,就会受到块清除的影响:

    l 将大量新数据批量加载到数据仓库中;

    l 在刚刚加载的所有数据上运行UPDATE(产生需要清理的块);

    l 让人们查询这些数据。

    9.4.6 日志竞争

    l redo放在一个慢速设备上:磁盘表现不佳。该购买速度更快的磁盘了。

    l redo与其他频繁访问的文件放在同一个设备上。redo设计为要采用顺序写,而且要放在专用的设备上。如果系统的其他组件(甚至其他Oracle组件)试图与LGWR同时读写这个设备,你就会遭遇某种程度的竞争。在此,只要有可能,你就会希望确保LGWR拥有这些设备的独占访问权限。

    l 已缓冲方式装载日志设备。你在使用一个“cooked”文件系统(而不是RAW磁盘)。操作系统在缓冲数据,而数据库也在缓冲数据(重做日志缓冲区)。这种双缓冲会让速度慢下来。如果可能,应该以一种“直接”方式了装载设备。具体操作依据操作系统和设备的不同而有所变化,但一般都可以直接装载。

    l redo采用了一种慢速技术,如RAID-5。RAID-5很合适读,但是用于写时表现则很差。前面已经了解了COMMIT期间会发生什么,我们必须等待LGWR以确保数据写到磁盘上。倘若使用的技术会导致这个工作变慢,这就不是一个好主意。



    9.4.7 临时表和redo/undo

    临时表不会为它们的块生成redo。因此,对临时表的操作不是“可恢复的” 。修改临时表中的一个块时,不会将这个修改记录到重做日志文件中。不过,临时表确实会生成 undo,而且这个 undo 会计入日志。因此,临时表也会生成一些redo。初看上去好像没有道理:为什么需要生成undo?这是因为你能回滚到事务中的一个 SAVEPOINT。由于undo数据必须建立日志,因此临时表会为所生成的undo生成一些重做日志。这样似乎很不好,不过没有你想像中那么糟糕。在临时表上运行的 SQL 语句主要是 INSERT 和SELECT。幸运的是,INSERT 只生成极少的 undo(需要把块恢复为插入前的“没有”状态,而存储“没有”不需要多少空间),另外SELECT根本不生成undo。

    注意:

    l 对“实际”表(永久表)的 INSERT 生成了大量 redo。而对临时表几乎没有生成任何 redo。这是有道理的,对临时表的INSERT只会生成很少的undo数据,而且对于临时表只会为undo数据建立日志。

    l 实际表的UPDATE生成的redo大约是临时表更新所生成redo的两倍。同样,这也是合理的。必须保存UPDATE的大约一半(即“前映像”)。对于临时表来说,不必保存“后映像”(redo)。

    l DELETE 需要几乎相同的redo空间。这是有道理的,因为对DELETE的 undo很大,而对已修改块的redo很小。因此,对临时表的DELETE与对永久表的DELETE几乎相同。

    因此,关于临时表上的DML 活动,可以得出以下一般结论:

    l INSERT 会生成很少甚至不生成undo/redo活动。

    l DELETE 在临时表上生成的redo与正常表上生成的redo同样多。

    l 临时表的UPDATE会生成正常表UPDATE一半的redo。

    有了以上了解,你可能会避免删除临时表。 可以使用TRUNCATE (当然要记住, TRUNCATE是 DDL,而 DDL 会提交事务,而且在 Oracle9i 及以前版本中,TRUNCATE 还会使你的游标失效) ,或者只是让临时表在 COMMIT 之后或会话终止时自动置空。执行方法不会生成 undo,相应地也不会生成 redo。你可能会尽量避免更新临时表,除非由于某种原因必须这样做。你会把临时表主要用于插入(INSERT)和选择(SELECT) 。采用这种方式,就能更优地使用临时表不生成redo的特有能力。



    9.5分析 undo

    9.5.1什么操作会生成最多和最少的 undo?

    一般来讲,INSERT 生成的 undo 最少,因为 Oracle 为此需记录的只是要“删除”的一个rowid(行ID) 。UPDATE 一般排名第二(在大多数情况下)。DELETE生成的 undo最多。与加索引列的更新相比,对一个未加索引的列进行更新不仅执行得更快,生成的 undo 也会好得多。而更新有索引的列则可能生成大量的undo,因为索引结构本身所固有的复杂性,而且我们更新了这个表中的每一行,移动了这个结构中的索引键值。



    9.5.2 ORA-01555: snapshot too old错误

    注意 ORA-01555 与数据破坏或数据丢失毫无关系。在这方面,这是一个“安全”的错误;惟一的影响是:接收到这个错误的查询无法继续处理。



    这个错误实际上很直接,其实只有两个原因,但是其中之一有一个特例,而且这种特例情况发生得如此频繁,所以我要说存在3 个原因:

    l undo段太小,不足以在系统上执行工作。

    l 你的程序跨COMMIT 获取(实际上这是前一点的一个变体)。我们在上一章讨论了这种情况。

    l 块清除。



    在充分说明这三种情况之前,我想先与你分享ORA-01555错误的几种解决方案,一般来说可以采用下面的方法:

    l 适当地设置参数 UNDO_RETENTION(要大于执行运行时间最长的事务所需的时间)。可以用V$UNDOSTAT来确定长时间运行的查询的持续时间。另外,要确保磁盘上已经预留了足够的空间,使undo 段能根据所请求的UNDO_RETENTION增大。

    l 使用手动 undo 管理时加大或增加更多的回滚段。这样在长时间运行的查询执行期间,覆盖undo数据的可能性就能降低。这种方法可以解决上述的所有3个问题。

    l 减少查询的运行时间(调优)。如果可能的话,这绝对是一个好办法,所以应该首先尝试这种方法。这样就能降低对 undo 段的需求,不需求太大的 undo 段。这种方法可以解决上述的所有3个问题。

    l 收集相关对象的统计信息。这有助于避免前面所列的第三点。 由于大批量的UPDATE或INSERT会导致块清除(block cleanout) ,所以需要在大批量UPDATE或大量加载之后以某种方式收集统计信息。



    对于Oracle9i 和以上版本,管理系统中的undo有两种方法:

    l 自动undo管理 (Automatic undo management):采用这种方法, 通过UNDO_RETENTION参数告诉 Oracle 要把 undo 保留多长时间。Oracle 会根据并发工作负载来确定要创建多少个undo段,以及每个undo段应该多大。数据库甚至在运行时可以在各个undo段之间重新分配区段,以满足DBA 设置的UNDO_RETENTION目标。这是undo管理的推荐方法。

    l 手动undo管理(Manual undo management) :采用这种方法的话,要由DBA 来完成工作。DBA 要根据估计或观察到的工作负载, 确定要手动地创建多少个undo 段。 DBA 根据事务量 (生成多少undo)和长时间运行查询的长度来确定这些undo段应该多大。



    在手动 undo 管理的情况下,DBA 要确定有多少个 undo 段,以及各个 undo 段有多大,这就产生了一个容易混淆的问题。有人说: “那好,我们已经配置了 XMB 的 undo,但是它们可以增长。我们把MAXEXTENTS 设置为 500,而且每个区段是 1MB,所以 undo 可以相当大。”问题是,倘若手动地管理undo段,undo段从来不会因为查询而扩大;只有INSERT、UPDATE 和DELETE才会让undo段增长。事实上,如果执行一个长时间运行的查询,Oracle不会因此扩大手动回滚段(即手动管理的回滚段)来保留数据,以备以后可能需要用到这些数据。只有当执行一个长时间运行的UPDATE 事务时才会扩大手动回滚段。在前面的例子中,即使手动回滚段有增长的潜力,但它们并不会真正增长。对于这样一个系统,你需要有更大的手动回滚段(尽管它们已经很大了)。你要永久地为回滚段分配空间,而不是只给它们自行增长的机会。对于这个问题,惟一的解决方案只能是适当地设置手动回滚段的大小。



    在自动undo 管理的情况下,从ORA-01555角度看,问题则要容易得多。无需自行确定undo空间有多大并完成预分配,DBA 只有告诉数据库运行时间至少在这段时间内保留 undo。如果已经分配了足够的空间可以扩展,Oracle 就会扩展 undo 段,而不是回绕,从而满足 UNDO_RETENTION 保持时间的要求。这与手动管理的 undo 截然相反,手动管理是会回绕,并尽可能块地重用 undo 空间。这是由于这个原因(即自动undo管理支持UNDO_RETENTION参数) ,所以我强烈建议尽可能采用自动undo 管理。

    使用手动undo管理时,还要记住重要的一点,遇到ORA-01555错误的可能性是由系统中最小的回滚段指示的(而非最大的回滚段,也并非平均大小的回滚段)。增加一个“大”回滚段不能解决这个问题。处理查询时只会让最小的回滚段回绕,这个查询就有可能遇到 ORA-01555 错误。使用遗留的回滚段时我主张回滚段大小要相等,以上就是原因所在。如果回滚段的大小都相等,那么每个回滚段即是最小的,也是最大的。这也是我为什么避免使用“最优大小”回滚段的原因。如果你收缩一个此前被扩大的回滚段,就要丢掉以后可能还需要的大量 undo。倘若这么做,会丢掉最老的回滚数据,从而力图使风险最小,但是风险还是存在。我喜欢尽可能在非高峰期间手动地收缩回滚段。

    我们已经讨论过块清除机制,不过这里可以做一个总结:在块清除过程中,如果一个块已被修改,下一个会话访问这个块时,可能必须查看最后一个修改这个块的事务是否还是活动的。一旦确定该事务不再活动,就会完成块清除,这样另一个会话访问这个块时就不必再历经同样的过程。要完成块清除, Oracle会从块首部确定前一个事务所用的undo段,然后确定从 undo 首部能不能看出这个块是否已经提交。可以用以下两种方式完成这种确认。一种方式是Oracle可以确定这个事务很久以前就已经提交,它在undo段事务表中的事务槽已经被覆盖。另一种情况是COMMIT SCN还在 undo段的事务表中,这说明事务只是稍早前刚提交,其事务槽尚未被覆盖。

    要从一个延迟的块清除收到ORA-01555错误,以下条件都必须满足:

    l 首先做了一个修改并COMMIT,块没有自动清理(即没有自动完成“提交清除” ,例如修改了太多的块,在SGA块缓冲区缓存的10%中放不下) 。

    l 其他会话没有接触这些块,而且在我们这个“倒霉”的查询(稍后显示)命中这些块之前,任何会话都不会接触它们。

    l 开始一个长时间运行的查询。这个查询最后会读其中的一些块。这个查询从SCN t1开始,这就是读一致 SCN,必须将数据回滚到这一点来得到读一致性。开始查询时,上述修改事务的事务条目还在undo段的事务表中。

    l 查询期间,系统中执行了多个提交。执行事务没有接触执行已修改的块(如果确实接触到,也就不存在问题了)。

    l 由于出现了大量的COMMIT,undo 段中的事务表要回绕并重用事务槽。最重要的是,将循环地重用原来修改事务的事务条目。另外,系统重用了 undo 段的区段,以避免对 undo 段首部块本身的一致读。

    l 此外,由于提交太多,undo段中记录的最低SCN 现在超过了t1(高于查询的读一致SCN)。



    如果查询到达某个块,而这个块在查询开始之前已经修改并提交,就会遇到麻烦。正常情况下,会回到块所指的undo段,找到修改了这个块的事务的状态(换句话说,它会找到事务的COMMIT SCN)。如果这个 COMMIT SCN 小于 t1,查询就可以使用这个块。如果该事务的 COMMIT SCN 大于 t1,查询就必须回滚这个块。不过,问题是,在这种特殊的情况下,查询无法确定块的COMMIT SCN是大于还是小于t1。相应地,不清楚查询能否使用这个块映像。这就导致了ORA-01555错误。



    万一你发现遭遇了这个问题,即选择(SELECT)一个表时(没有应用其他DML操作)出现了ORA-01555错误,能你可以试试以下解决方案:

    l 首先,保证使用的事务“大小适当”。确保没有不必要地过于频繁地提交。

    l 使用 DBMS_STATS 扫描相关的对象,加载之后完成这些对象的清理。由于块清除是极大量的UPDATE 或INSERT造成的,所以很有必要这样做。

    l 允许undo表空间扩大,为之留出扩展的空间,并增加undo保持时间。这样在长时间运行查询期间,undo 段事务表中的事务槽被覆盖的可能性就会降低。针对导致ORA-01555错误的另一个原因(undo 段太小) ,也同样可以采用这个解决方案(这两个原因有紧密的关系;块清除问题就是因为处理查询期间遇到了 undo 段重用,而 undo 段大小正是重用 undo 段的一个根本原因) 。实际上,如果把undo表空间设置为一次自动扩展1MB,而且undo保持时间为900秒,再运行前面的例子,对表BIG 的查询就能成功地完成了。

    l 减少查询的运行时间(调优)。如果可能的话,这总是件好事,所以应该首先尝试这样做。
    展开全文
  • 码了自己用。。。  # 一级标题 ## 二级 ### 三级 #### 四级 ##### 五级 ###### 六级 - 列表文本1 ... 我这个是引用别人的话哦 *斜体* **加粗** ``` 代码区 代码区 ``` 你好我在实施 [连接...

    码了自己用。。。 

    # 一级标题
    ## 二级
    ### 三级
    #### 四级
    ##### 五级
    ###### 六级
    - 列表文本1
    - 列表文本2
    - 列表文本3
    
    1. 文本
    2. 文本
    3. 文本
    
    [文本](http://www.baidu.com)
    > 一盏灯
    > 我这个是引用别人的话哦
    
    *斜体*
    **加粗**
    
    ```
    代码区
    
    
    代码区
    ```
    你好我在实施
    [连接]()
    
    [p+链接][1]
    [1]:http://www.baidu.com "我是链接"
    
    ![我是张图连接][id]
    [id]: http://images0.zaijiawan.com/wechat/recommend/5.png@!ori "我是图"
    
    <p>这是啥</p><p>操作</p>
    
    
    
    

    样式:

    一级标题

    二级

    三级

    四级

    五级

    六级

    • 列表文本1
    • 列表文本2
    • 列表文本3

    1. 文本
    2. 文本
    3. 文本

    文本

    一盏灯 我这个是引用别人的话哦

    斜体 加粗

    代码区
    
    
    代码区

    你好我在实施 连接

    p+链接

    我是张图连接

    这是啥

    操作

     

     

    展开全文
  • 修改项目文件编码

    千次阅读 2014-09-02 14:42:16
    直接引用,中文会乱码,因此要将编码格式改为UTF-8,源代码文件太多,如果手动改的话,工作量可想而知, 自然而然的想到,找个自动改编码的程序,从网上找了个小程序,非常简单,就一个Java类,执行main方法即可。 ...

    最近接手一个别人的项目,该项目要改造后作为依赖引入到另外一个项目中。

    改造时发现,此项目的编码格式为GBK,而目标项目的编码格式为UTF-8。

    直接引用,中文会乱码,因此要将编码格式改为UTF-8,源代码文件太多,如果手动改的话,工作量可想而知,

    自然而然的想到,找个自动改编码的程序,从网上找了个小程序,非常简单,就一个Java类,执行main方法即可。

    其中引用了Jodd项目(http://jodd.org/),具体代码如下:

    package com;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    import jodd.io.FileNameUtil;
    import jodd.io.FileUtil;
    
    /**
     * 项目源文件格式转换(Java文件)
     */
    public class ConvertEncodingUtil {
    	
    	private static final String UTF8 = "UTF-8";
    	private static final String GBK = "GBK";
    	
    	public static void main(String[] args) {
    		String srcDir = "F:\\src\\Demo";
    		String targetDir = "E:\\target\\Demo";
    		
    		ConvertEncodingUtil con = new ConvertEncodingUtil();
    		try {
    			con.convertEncoding2UTF8(srcDir, targetDir, GBK);
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	/**
    	 * @param srcDir 源文件所在目录
    	 * @param targetDir 目标文件目录
    	 * @param srcEncoding 源文件编码
    	 */
    	public void convertEncoding2UTF8(String srcDir, String targetDir, String srcEncoding) throws IOException {
    		this.convertEncoding(srcDir, targetDir, srcEncoding, UTF8);
    	}
    	
    	/**
    	 * @param srcEncoding 源文件编码
    	 * @param targetEncoding 目标编码
    	 */
    	public void convertEncoding(String srcDir, String targetDir, String srcEncoding, String targetEncoding) throws IOException {
    		
    		if(isNullOrEmpty(srcDir)) {
    			System.out.println(srcDir + "is not exists...");
    			return;
    		}
    		
    		File srcFile = new File(srcDir);
    		if(!srcFile.exists()) {
    			System.out.println(srcDir + "is not exists...");
    			return;
    		} else if(srcFile.isFile()) {
    			System.out.println(srcDir + "is not a directory!");
    			return;
    		}
    		
    		if(isNullOrEmpty(targetDir)) {
    			System.out.println(targetDir + "is not exists...");
    			return;
    		}
    		
    		File dir = new File(targetDir);
    		
    		if(dir.isFile()) {
    			System.out.println(targetDir + "is not a directory!");
    			return;
    		} else if(!dir.exists()) {
    			dir.mkdirs();
    		}
    		
    		// 获取所有java文件
    		List<File> list = getAllSubFiles(srcDir);
    		
    		for(File file : list) {
    			// 转码后的文件路径
    			String absPath = targetDir + file.getAbsolutePath().substring(srcDir.length());
    			// 使用 srcEncoding 读取数据,然后用 targetEncoding 写入数据
    			String path = FileNameUtil.getFullPath(absPath);
    			File pf = new File(path);
    			if(!pf.exists()) {
    				pf.mkdirs();
    			}
    			
    			FileUtil.writeString(absPath, FileUtil.readString(file, srcEncoding), targetEncoding);
    			//FileUtils.writeLines(new File(absPath), "UTF-8", FileUtils.readLines(file, "GBK"));
    		}
    	}
    
    	private List<File> getAllSubFiles(String dirName) {
    		List<File> files = new ArrayList<File>();
    		File rootDir = new File(dirName);
    		if (rootDir.isDirectory()) {
    			File[] allFiles = rootDir.listFiles();
    			for (File file : allFiles) {
    				if (file.isDirectory()) {
    					files.addAll(getAllSubFiles(file.getAbsolutePath()));
    				} else if (FileNameUtil.getExtension(file.getName()).equalsIgnoreCase("java")) {
    					files.add(file);
    				}
    			}
    		}
    		return files;
    	}
    	
    	private boolean isNullOrEmpty(String arg) {
    		return arg == null || arg.trim().equals("");
    	}
    }


    展开全文
  • MarKDown学习

    2021-02-01 20:37:52
    MarkDown学习 标题 格式 n# + 空格 + 内容 (n表示空格的个数,即标题的级数 ...当我们需要引用别人的话时,可以使用大于号加上你想表达的内容 这是个引用 分割线 格式: — 或 *** 图片 格式: ! + [你的图片名
  • 有一点道理,实验室boss 们表面上就是靠一串串ppt 行走江湖。经常有研究生因思维敏捷条例清楚而令人肃然起敬。也经常有研究生不理解"为什么我做了大部分工作而老板却让另一个没怎么干活人写了文章?让他去...
  • 还是引用环球网特约评论员于斌老师一句更能说明问题:  “外包公司因为其业务特性,一个项目接着一个项目。对于员工技能要求相对不高,能干活就行,提升很难,并且很难接触到核心功能模块,基本上都是别人...
  • markdown常用语法

    2021-01-17 23:12:21
    markdown常用语法 标题 标题分为一级标题二级标题等,markdown...引用别人的话,达到引用的效果 图片格式 ![文字描述]再加括号,括号中写图片地址,地址可以是本地也可以是网络地址 分割线 直接用三个减号 **使用三
  • 简介本文介绍Markdown的基本使用方法: 使用标题 加粗、斜体 分割线 列表 引用 我写博客一般将可以独立的内容分节...引用,可以用来做注意说明,也可以用来写引用的内容,比如别人说过的话。下面我们一一说明这些格式
  • Markdown

    2021-03-15 17:08:38
    Markdown的基础语法 一、标题格式 1. 一级标题:ctal+1 或者 #加标题 2. 二级标题:ctal+2 或者 ##加...引用别人的话的时候用 语法:>加空格 四、分割线 三个—或者三个***都可以实现 五、图片 [外链图片转存失
  • 2021-04-17

    2021-04-17 20:50:42
    MarkDown语法 推荐文本编辑器:Typora 文件后缀xxx.md ...选择 :引用别人的话 4.分割线 —:三根减号 ***:三个星号 5.图片 ![图片名称](本地图片的地址本地存放的图片):存放本地上的图片 ![图片名称]
  • html基础内容样式

    2017-08-24 09:16:49
    head 编码格式:让浏览器可以识别中文 作者 ...关键字:用户搜索时候可以通过关键字搜索到该网页 ...网站描述信息 ...h1~h6:标题标签,重要性依次递减,字体默认... 引用别人一段 强调文本为重要文本,字体加粗
  • 毕业论文经验

    千次阅读 2015-07-14 21:29:56
    以前总听学长学姐们抱怨论文烦答辩烦,想想不就写一个字多的作文嘛有啥难的。最近轮到自己写论文了,才知此中...别以为复制了别人的一段话然后再结尾弄个[1]就不会被查重了,真是如此的话全篇引用都能过了,所以就算标
  • 这是一套交谈十二法则幻灯片优秀欣赏,第一PPT模板网提供幻灯片免费下载。 本PPT分1十二也讲述了谈话注意事项和法则,...11.不要错误的引用; 12.培养你圆滑,养成习惯; 关键词:优秀幻灯片下载,.PPTX格式
  • 嗨,你真懂this吗?

    2020-12-02 23:21:09
    那么在看别人的代码或者是源码的时候,就会很吃力。</li><li>工作中,滥用this,却没明白this指向的是什么,而导致出现问题,但是自己却不知道哪里出问题了。【在公司,我至少...
  • 7.5.2 通用键引用 322 7.5.3 对非结构化数据过度使用 325 7.6 总结 326 7.7 回顾与展望 326 第8章 数据访问安全 328 8.1 安全主体与安全对象 329 8.2 数据库安全概述 330 8.2.1 模拟 331 8.2.2 权限 333 ...
  • 7.5.2 通用键引用 322 7.5.3 对非结构化数据过度使用 325 7.6 总结 326 7.7 回顾与展望 326 第8章 数据访问安全 328 8.1 安全主体与安全对象 329 8.2 数据库安全概述 330 8.2.1 模拟 331 8.2.2 权限 333 ...
  • –说在前面的话 这个博客格式有点乱,但是应该无伤大雅 当别人问你这是什么东西的时候,你要从下面几点回答 1、定义。2、功能(作用)。3、底层实现(简单讲)。4、优缺点。5、自己掌握的程度 –href和src的区别 ...
  • 一个好用数据库类

    2008-05-14 08:36:06
    <br>四、总结 ODBC有很多用处,例如我们可以把很多信息按照一定的格式保存在文本中(因为在商业上用别人的数据库都是要买的),然后通过ODBC把这些文本文件映射成表,这些文件的目录就成为一个数据库,这些...
  • markdown基本语法

    2021-03-09 19:21:19
    Typora的使用 ...”+空格为引用别人的话 三个“*”为分割线 图片 “!”+“【】”为图片 超链接 “[]”+"()"为超链接,“()”中写链接 列表 “1.”+空格或c t r l+shift+[为有序列表
  • vue之axios封装

    千次阅读 2019-01-17 11:36:50
    本想使用axios,但不封装的话,使用起来太臃肿,此封装方式是根据别人封装格式改造过来使用,地址在最下面。 1.axios安装: npm install axios -D 2.封装axios,index.js /** 接口调用工具*/ import axios ...
  • 本想使用axios,但不封装的话,使用起来太臃肿,此封装方式是根据别人封装格式改造过来使用,地址在最下面。 1.axios安装: npm install axios -D 2.封装axios,index.js /** 接口调用工具*/ import axios from '...
  • 是,Linux 上有公认 C 语言世界最好编译器 gcc,如果你想得到一个效率更高开 发环境(并不一定是最友好,但一定是最强大),我建议你一定要好好熟悉一下 Linux。 三.如何得到Linux? 据我所知...
  • php高级开发教程说明

    2008-11-27 11:39:22
    尽管你项目并不是一个真正敌人,这句话的寓意仍然适用,在转向其他题目 时,要知道项目所有技术条件、目标平台、用户,并且决不要低估那些没有考虑周全小问 题重要性。 据我们经验,计划占用了5 0 %...
  • vc++ 应用源码包_1

    热门讨论 2012-09-15 14:22:12
    引用了Splayer中Sqlite3库,进行了测试。 SrcFirstProg 简单窗口程序。 SuperGrid - 特别 listview 控件 网格形式视图,自绘了CComboBox、CEdit、CSuperGridCtrl实现。 tab 演示了CTabCtrl控件使用方法...
  • K File Converter V1.1.1 CN

    2007-05-18 23:39:07
    <br/>K File Converter正是为了解决这个问题而设计,用户无论是使用别人的工具还是自己开发的工具,都无需为了对图形界面和对文件夹以及文件过滤的支持而浪费时间。 <br/>其中软件预置的转换器主要有4种,...
  • vc++ 应用源码包_6

    热门讨论 2012-09-15 14:59:46
    引用了Splayer中Sqlite3库,进行了测试。 SrcFirstProg 简单窗口程序。 SuperGrid - 特别 listview 控件 网格形式视图,自绘了CComboBox、CEdit、CSuperGridCtrl实现。 tab 演示了CTabCtrl控件使用方法...
  • vc++ 应用源码包_2

    热门讨论 2012-09-15 14:27:40
    引用了Splayer中Sqlite3库,进行了测试。 SrcFirstProg 简单窗口程序。 SuperGrid - 特别 listview 控件 网格形式视图,自绘了CComboBox、CEdit、CSuperGridCtrl实现。 tab 演示了CTabCtrl控件使用方法...
  • vc++ 应用源码包_5

    热门讨论 2012-09-15 14:45:16
    引用了Splayer中Sqlite3库,进行了测试。 SrcFirstProg 简单窗口程序。 SuperGrid - 特别 listview 控件 网格形式视图,自绘了CComboBox、CEdit、CSuperGridCtrl实现。 tab 演示了CTabCtrl控件使用方法...
  • EXCE使用技巧

    2012-12-08 20:48:59
    这里要注意,它提供了两层保护,如果你也设置了修改权限密码的话,那么即使文件被打开也还需要输入修改权限的密码才能修改;  ⑶、单击"确定"按钮,在弹出的密码确认窗口中重新输入一遍密码,再点击"确认",最后点...

空空如也

空空如也

1 2 3
收藏数 51
精华内容 20
关键字:

引用别人的话格式