标签 数据库 下的文章

typecho博客网站更换域名


登录 MySQL 执行:
注意:以下 SQL 语句使用默认表前缀 typecho_,操作数据库前建议备份。


# 修改网站设置里的域名:
UPDATE `typecho_options` SET `value` = '新域名' WHERE `typecho_options`.`name` = 'siteUrl' AND `typecho_options`.`user` =0;

# 替换文章的域名
UPDATE `typecho_contents` SET `text` = REPLACE(`text`,'原域名','新域名');

# 将管理员的个人网站进行替换
UPDATE `typecho_users` SET `url` = REPLACE(`url`,'原域名','新域名');

# 替换评论中的域名
UPDATE `typecho_comments` SET `url` = REPLACE(`url`,'原域名','新域名');
UPDATE `typecho_comments` SET `text` = REPLACE(`text`,'原域名','新域名');
```sql

互联网面试常见问题整理


高并发系统之限流特技
动态链接库中函数的地址确定---PLT和GOT
Linux 中的各种栈:进程栈 线程栈 内核栈 中断栈
Redis和Memcached的区别
epoll内核源码详解+自己总结的流程
后台开发面试问题整理
Linux内核:poll机制
linux任务调度机制
Linux内核:poll机制
解读Raft(一 算法基础) - 杭州.Mark - 博客园
Linux文件系统详解 - AlanTu - 博客园
Linux c 开发 - 内存管理器ptmalloc - CSDN博客
Linux环境变量及其设置 - CSDN博客
比较全面的gdb调试命令 - 知识天地 - 博客园
把握linux内核设计思想(六):内核时钟中断 - CSDN博客
Linux进程调度原理 - alex.shu - 博客园
Linux系统调用的实现机制分析 - CSDN博客
理解inode - 阮一峰的网络日志
多阶hash表 - juary_的专栏 - CSDN博客
理解 glibc malloc - CSDN博客
Redis与Memcached的比较-zpf1218-ChinaUnix博客
glibc中malloc的详细解释 - CSDN博客
Redis的那些最常见面试问题 - 回首笑人间 - 博客园
浅析基于glibc的malloc - CSDN博客
slab机制 - wangLinuxer - 博客园
有感于STL的内存管理
DNS使用的是TCP协议还是UDP协议 - qq100440110的专栏 - CSDN博客
Linux的任务调度机制 - Nicholas的专栏 - CSDN博客
进程—内存描述符(mm_struct) - CSDN博客
彻底弄懂HTTP缓存机制及原理 - 木上有水 - 博客园
利用CAS操作(Compare & Set)实现无锁队列 - CSDN博客
进程间通信的方式——信号、管道、消息队列、共享内存 - 0giant - 博客园
TCP的数据流——滑动窗口,拥塞窗口,慢启动,Nagle算法,经受时延的确认等 - 千里之外 - CSDN博客
TCP协议总结--停止等待协议,连续ARQ协议,滑动窗口协议 - 杨博东的博客 - 博客园
C/C++ 笔试、面试题目大汇总 - fangyukuan - 博客园
C/C++ 内存对齐原则及作用 - chy19911123的专栏 - CSDN博客
mysql数据库面试总结 - bullets - 博客园
[学习笔记]数据库设计三大范式与BCNF,学习笔记 - ybwang1989 - 博客园
常见面试题整理--数据库篇(每位开发者必备) - weinierzui的专栏 - CSDN博客
知识库 - 你身边的技术百科全书 - CSDN
进程上下文与线程上下文 - bingshanyijiao_fkx的专栏 - CSDN博客
linux线程切换和进程切换的方法_Linux_脚本之家
深入理解计算机系统之虚拟存储器 - Al_xin的专栏 - CSDN博客
tcp的半连接与完全连接队列 - go4it - 简书
数位dp总结 之 从入门到模板 - 努力 - CSDN博客
类中函数的重载、隐藏和覆盖 - beaglebone - 博客园
排序算法____基数排序 - Dingwj_blog - 博客园
面试题干货在此_讨论区_牛客网
排序算法系列:基数排序 - 大鱼 - CSDN博客
位图索引:原理(BitMap index) - zhanlijun - 博客园
fopen与open的区别 - 清清飞扬 - 博客园
《深入理解计算机系统》-虚拟存储器 - gatsby_dhn - 简书
Linux内核解析:进程间通信:管道 - 笨拙的菜鸟 - 博客园
参考别人的面试总结:linux C/C++服务器后台开发面试题总结 - 大孟的博客 - CSDN博客
linux C/C++服务器后台开发面试题总结 - Nancy26 - 博客园
ELF 文件中的section 和 segment - wo_der的博客 - CSDN博客
聊聊Linux动态链接中的PLT和GOT(1)——何谓PLT与GOT - 海枫的专栏 - CSDN博客
ELF文件的加载和动态链接过程 - - ITeye博客
ELF文件的加载过程(load_elf_binary函数详解)--Linux进程的管理与调度(十三) - AderStep - CSDN博客
linux awk命令详解 - ggjucheng - 博客园
IP分片和TCP分片的区别 - cumirror的专栏 - CSDN博客
fork()----父子进程共享 - 程序狗的成长之路 - CSDN博客
Makefile中的wildcard用法 - liangkaiming的专栏 - CSDN博客
深入理解C++的动态绑定和静态绑定 - 常高伟的专栏 - CSDN博客
C++模板元编程(C++ template metaprogramming) - 文章 - 伯乐在线
C++后台开发校招面试常见问题 - oscarwin - CSDN博客
互斥锁的实现(转) - hzhzh007的专栏 - CSDN博客
TCP-IP详解:糊涂窗口综合症(Silly Window syndrome) - 深邃 精致 内涵 坚持 - CSDN博客
浅析Linux下的task_struct结构体 - qq_29503203的博客 - CSDN博客
C++虚继承的概念 - crystal_avast的专栏 - CSDN博客
c++ 虚继承与继承的差异 - Kikim的地盘 - CSDN博客
Linux的inode的理解 - iTech - 博客园
IPC通信:Posix消息队列 - liuhongxiangm的专栏 - CSDN博客
Linux线程的信号量同步 - JollyWing - 博客园
Linux进程间通信——使用共享内存 - ljianhui的专栏 - CSDN博客
gdb调试coredump(使用篇) - 叶落无痕,枫过有情…… - CSDN博客
信号中断 与 慢系统调用 - 许振坪的专栏 - CSDN博客
浅析CPU中断技术 - Funeral - 博客园
Linux信号(signal) 机制分析 - h13 - 博客园
EPOLLIN , EPOLLOUT , EPOLLPRI, EPOLLERR 和 EPOLLHUP事件 - yingying.liu的专栏 - CSDN博客
三种工厂模式的分析以及C++实现 - 曾经的你| - 博客园
STL源码剖析---红黑树原理详解上 - Hackbuteer1的专栏 - CSDN博客
valgrind 的使用简介 - sduliulun的专栏 - CSDN博客
_unix linux_脚本之家
GDT(Global Descriptor Table)全局描述符表 - starlitnext - 博客园
Linux程序加载过程 - 赢在拼搏中 - CSDN博客
linux 用户空间与内核空间——高端内存详解 - 立超的专栏 - 博客园
Linux虚拟地址空间布局以及进程栈和线程栈总结 - wilcohuang's blog - CSDN博客
堆排算法的分析与总结 - HOU_JUN - 博客园
HTTP必知必会——常见面试题总结 - Leeon的博客 - CSDN博客
pthread_once单例模式 - tom555cat - CSDN博客
pthread_once()使用(某个时间在整个程序中仅执行一次,不确定是那个线程) - 轻飘飞扬 - CSDN博客
23种设计模式对比与总结 - 码农恋码 - 博客园
ORM框架使用优缺点 - public - CSDN博客
高性能服务开发之定时器 - 行健 - 博客园
Https协议详解 - CoderZhuang - 博客园
图解SSL/TLS协议 - 阮一峰的网络日志
HTTPS 原理解析 - Zery - 博客园
Linux的用户和用户组管理 - 风生水起 - 博客园
TCP系列13—重传—3、协议中RTO计算和RTO定时器维护 - lshs - 博客园
可执行文件(ELF)格式的理解 - 深海的小鱼儿 - 博客园
GCC/G++编译参数含义 - yasi_xi的专栏 - CSDN博客
Linux内核中cache的实现 - leopard_ray的专栏 - CSDN博客
epoll源码实现分析[整理] - Apprentice89 - 博客园
linux内核内存管理学习之三(slab分配器) - 浩海拾贝 - CSDN博客
深度理解select、poll和epoll - 傻眼哥的博客 - CSDN博客
【经典算法】——KMP,深入讲解next数组的求解 - c_cloud - 博客园
Linux中断(interrupt)子系统之一:中断系统基本原理 - DroidPhone的专栏 - CSDN博客
HTTP Session、Cookie机制详解 - 奔跑的001 - 博客园
HttpSession详解 - 别再顺其自然 - 博客园
HTTP的长连接和短连接 - 烛秋 - 博客园
自动化构建 - 百度
linux内核之进程的基本概念(进程,进程组,会话关系) - 笨拙的菜鸟 - 博客园
Linux--进程组、会话、守护进程 - Alex_Monkey - 博客园
银行家算法学习笔记 - 唯心不易 - 博客园
linux session 浅谈 - younghongjian的专栏 - CSDN博客
Linux-进程、进程组、作业、会话、控制终端详解 - John_ABC - 博客园
关系型数据库到文档型数据库的跨越 - 海天一色是黑色的博客 - CSDN博客
linux系统编程之进程(八):守护进程详解及创建,daemon()使用 - mickole - 博客园
数据库设计三大范式 - Ruthless - 博客园
常见面试题整理--数据库篇 - 铭记遗忘 - 博客园
谈谈数据库的ACID - 敦格 - CSDN博客
关于TCP乱序和重传的问题 - cws1214的专栏 - CSDN博客
DNS 原理入门 - 阮一峰的网络日志
数据结构专题——线段树 - MetalSeed - CSDN博客
一步一步理解线段树 - tenos - 博客园
mysql 数据表读锁机制详解 - joy696163 - 博客园
单例模式全面学习(C++版) - weixliu - 博客园
单例模式及C++实现代码 - 曾经的你| - 博客园
每天进步一点点——五分钟理解一致性哈希算法(consistent hashing) - Cynric 的博客 - CSDN博客
TCP 协议中MSS的理解-frankzfz-ChinaUnix博客
TCP/IP详解学习笔记(15)-- TCP的流量控制和拥塞控制 - newwy - 博客园
TCP/IP详解--拥塞控制 & 慢启动 快恢复 拥塞避免 - losbyday - 博客园
关于C++中公有继承、私有继承、保护继承的讨论 - This is bill的专属博客 - CSDN博客
解决Hash碰撞冲突方法总结 - zeb_perfect的专栏 - CSDN博客
Linux进程通信之POSIX共享内存 - anonymalias的专栏 - CSDN博客
IPC对象持续性 - xiaohuima_dong的专栏 - CSDN博客
Linux环境进程间通信(三):消息队列-hnsyspc-ITPUB博客
Linux进程同步之POSIX信号量 - anonymalias的专栏 - CSDN博客
进程/线程同步的方式和机制,进程间通信 - Icnblog_Wan - 博客园
Linux进程同步之记录锁(fcntl) - jlins - 博客园
Linux 伙伴算法简介 - 浩天之家 - 博客园
孤儿进程与僵尸进程[总结] - Anker's Blog - 博客园
Linux虚拟地址空间布局以及进程栈和线程栈总结 - Xzzzh - 博客园
linux 内核poll/select/epoll实现剖析 - 在思考的路上 - ITeye博客
Linux虚拟地址空间布局 - clover_toeic - 博客园
HTTP详解(1)-工作原理 - guisu,程序人生。 逆水行舟,不进则退。 - CSDN博客
epoll简介及触发模式(accept、read、send) - 留下的只是回忆 - 博客园
linux内核分析笔记----中断和中断处理程序 - ☆&寒 烟☆ - 博客园
标准IO与文件IO 的区别 - bigbit的博客 - CSDN博客
硬中断和软中断 - zhangskd的专栏 - CSDN博客
<A HREF="http://m.blog.csdn.net/wenhui
/article/details/6889013">可重入和不可重入 - wenhui_的专栏 - CSDN博客
浅谈数位DP - zbtrs - 博客园
C++ Queues(队列)、Priority Queues(优先队列) - 面对现实,超越自己 - C++博客
缓存淘汰算法--LRU算法 - 小程故事多 - ITeye博客
Linux内核中内存cache的实现-yfydz-ChinaUnix博客
socket编程中write、read和send、recv之间的区别 - petershina的专栏 - CSDN博客
彻底学会使用epoll(六)——关于ET的若干问题总结 - feeman的专栏 - CSDN博客
linux系统编程之进程(八):守护进程详解及创建,daemon()使用 - mickole - 博客园
Linux IO模式及 select、poll、epoll详解 - 人云思云 - SegmentFault
select、poll、epoll之间的区别总结[整理] - Anker's Blog - 博客园
树状数组彻底入门 - 半根毛线 - 博客园
C++的new、delete及其内存管理 - Kelvin_Yan的专栏 - CSDN博客
malloc 函数详解 - Commence - 博客园
浅谈数据库查询优化的几种思路 - 六尺帐篷 - 简书
硬中断与软中断的区别_Linux编程_Linux公社-Linux系统门户网站
信号的基本概念、信号的产生以及阻塞信号 - 滴巴戈 - 博客园
Linux信号(signal) 机制分析 - h13 - 博客园
linux中断--LINUX中断机制与信号 - 鱼思故渊的专栏 - CSDN博客
进程线程及堆栈关系的总结 - echoisland的专栏 - CSDN博客
栈帧之深入理解c函数调用过程 - jelly_9的博客 - CSDN博客
【经典数据结构】B树与B+树 - vincently - 博客园
linux 物理内存和虚拟内存 - 百度
C/C++函数调用过程分析 - as_ - 博客园
胜者树与败者树 - whz_zb的专栏 - CSDN博客
Epoll详解及源码分析 - 我有我的天空 - CSDN博客
环回地址 - 百度
拓扑排序的原理及其实现 - dm_vincent的专栏 - CSDN博客
Manacher算法--O(n)回文子串算法 - xuanflyer - CSDN博客
【转】二叉树、B树、B-树、B+树、B树 - zhzhang - 博客园
设计模式 之 单例模式 (C++ 懒汉经典实现 & DCL实现 & 饿汉经典实现) - 柠檬不加糖的博客 - CSDN博客
C++中的单例模式 - Hackbuteer1的专栏 - CSDN博客
【C/C++】对于可重入、线程安全、异步信号安全几个概念的理解 - ZhangPY的专栏 - CSDN博客
B树、B-树、B+树、B
树详解(转) - 憨熊之家 - 博客园
红黑树(一)之 原理和算法详细介绍 - 如果天空不死 - 博客园
分布式锁的三种实现方式 - - ITeye技术网站
平衡二叉树详解 - zhangbaochong - 博客园
n个数中任意两个异或最大值


数据库事务那些事


Transaction 也就是所谓的事务了,通俗理解就是一件事情。从小,父母就教育我们,做事情要有始有终,不能半途而废。 事务也是这样,不能做一般就不做了,要么做完,要么就不做。也就是说,事务必须是一个不可分割的整体,就像我们在化学课里学到的原子,原子是构成物质的最小单位。于是,人们就归纳出事务的第一个特性:原子性(Atomicity)。我靠,一点都不神秘嘛。

特别是在数据库领域,事务是一个非常重要的概念,除了原子性以外,它还有一个极其重要的特性,那就是:一致性(Consistency)。也就是说,执行完数据库操作后,数据不会被破坏。打个比方,如果从 A 账户转账到 B 账户,不可能因为 A 账户扣了钱,而 B 账户没有加钱吧。如果出现了这类事情,您一定会非常气愤,什么 diao 银行啊!

当我们编写了一条 update 语句,提交到数据库的一刹那间,有可能别人也提交了一条 delete 语句到数据库中。也许我们都是对同一条记录进行操作,可以想象,如果不稍加控制,就会出大麻烦来。我们必须保证数据库操作之间是“隔离”的(线程之间有时也要做到隔离),彼此之间没有任何干扰。这就是:隔离性(Isolation)。要想真正的做到操作之间完全没有任何干扰是很难的,于是乎,每天上班打酱油的数据库专家们,开始动脑筋了,“我们要制定一个规范,让各个数据库厂商都支持我们的规范!”,这个规范就是:事**务隔离级别(Transaction Isolation Level)。**能定义出这样牛逼的规范真的挺不容易的,其实说白了就四个级别:

  1. READ_UNCOMMITTED
  2. READ_COMMITTED
  3. REPEATABLE_READ
  4. SERIALIZABLE

千万不要去翻译,那只是一个代号而已。从上往下,级别越来越高,并发性越来越差,安全性越来越高,反之则反。

当我们执行一条 insert 语句后,数据库必须要保证有一条数据永久地存放在磁盘中,这个也算事务的一条特性, 它就是:持久性(Durability)

归纳一下,以上一共提到了事务的 4 条特性,把它们的英文单词首字母合起来就是:ACID,这个就是传说中的“事务 ACID 特性”!

真的是非常牛逼的特性啊!这 4 条特性,是事务管理的基石,一定要透彻理解。此外还要明确,这四个家伙当中,谁才是老大?

其实想想也就清楚了:原子性是基础,隔离性是手段,持久性是目的,真正的老大就是一致性。数据不一致了,就相当于“江湖乱套了,流氓戴胸罩”。所以说,这三个小弟都是跟着“一致性”这个老大混,为他全心全意服务。

这四个家伙当中,其实最难理解的反倒不是一致性,而是隔离性。因为它是保证一致性的重要手段,是工具,使用它不能有半点差池,否则后果自负!怪不得数据库行业专家们都要来研究所谓的事务隔离级别了。其实,定义这四个级别就是为了解决数据在高并发下所产生的问题,那又有哪些问题呢?

  1. Dirty Read(脏读)
  2. Unrepeatable Read(不可重复读)
  3. Phantom Read(幻读)

首先看看“脏读”,看到“脏”这个字,我就想到了恶心、肮脏。数据怎么可能脏呢?其实也就是我们经常说的“垃圾数据”了。比如说,有两个事务,它们在并发执行(也就是竞争)。看看以下这个表格,您一定会明白我在说什么:

时间 事务 A(存款) 事务 B(取款)
T1 开始事务
T2 开始事务
T3 查询余额(1000 元)
T4 取出 1000 元(余额 0 元)
T5 查询余额(0 元)
T6 撤销事务(余额恢复为 1000 元)
T7 存入 500 元(余额 500 元)
T8 提交事务

余额应该为 1500 元才对!请看 T5 时间点,事务 A 此时查询余额为 0 元,这个数据就是脏数据,它是事务 B 造成的,明显事务没有进行隔离,渗过来了,乱套了。

所以脏读这件事情是非常要不得的,一定要解决掉!让事务之间隔离起来才是硬道理。

那第 2 条,不可重复读又怎么解释呢?还是用类似的例子来说明:

时间 事务 A(存款) 事务 B(取款)
T1 开始事务
T2 开始事务
T3 查询余额(1000 元)
T4 查询余额(1000 元)
T5 取出 1000 元(余额 0 元)
T6 提交事务
T7 查询余额(0 元)

事务 A 其实除了查询了两次以外,其他什么事情都没有做,结果钱就从 1000 变成 0 了,这就是重复读了。可想而知,这是别人干的,不是我干的。其实这样也是合理的,毕竟事务 B 提交了事务,数据库将结果进行了持久化,所以事务 A 再次读取自然就发生了变化。

这种现象基本上是可以理解的,但在有些变态的场景下却是不允许的。毕竟这种现象也是事务之间没有隔离所造成的,但我们对于这种问题,似乎可以忽略。

最后一条,幻读。我去!Phantom 这个单词不就是“幽灵、鬼魂”吗?刚看到这个单词时,真的把我的小弟弟都给惊呆了。怪不得这里要翻译成“幻读”了,总不能翻译成“幽灵读”、“鬼魂读”吧。其实意义就是鬼在读,不是人在读,或者说搞不清楚为什么,它就变了,很晕,真的很晕。还是用一个示例来说话吧:

时间 事务 A(统计总存款) 事务 B(存款)
T1 开始事务
T2 开始事务
T3 统计总存款(10000 元)
T4 存入 100 元
T5 提交事务
T6 统计总存款(10100 元)

银行工作人员,每次统计总存款,都看到不一样的结果。不过这也确实也挺正常的,总存款增多了,肯定是这个时候有人在存钱。但是如果银行系统真的这样设计,那算是玩完了。这同样也是事务没有隔离所造成的,但对于大多数应用系统而言,这似乎也是正常的,可以理解,也是允许的。银行里那些恶心的那些系统,要求非常严密,统计的时候,甚至会将所有的其他操作给隔离开,这种隔离级别就算非常高了(估计要到 SERIALIZABLE 级别了)。

归纳一下,以上提到了事务并发所引起的跟读取数据有关的问题,各用一句话来描述一下:

  1. 脏读:事务 A 读取了事务 B 未提交的数据,并在这个基础上又做了其他操作。
  2. 不可重复读:事务 A 读取了事务 B 已提交的更改数据。
  3. 幻读:事务 A 读取了事务 B 已提交**的新增数据。**

第一条是坚决抵制的,后两条在大多数情况下可不作考虑。

这就是为什么必须要有事务隔离级别这个东西了,它就像一面墙一样,隔离不同的事务。看下面这个表格,您就清楚了不同的事务隔离级别能处理怎样的事务并发问题:

事务隔离级别 脏读 不可重复读 幻读
READ_UNCOMMITTED 允许 允许 允许
READ_COMMITTED 禁止 允许 允许
REPEATABLE_READ 禁止 禁止 允许
SERIALIZABLE 禁止 禁止 禁止

根据您的实际需求,再参考这张表,最后确定事务隔离级别,应该不再是一件难事了。

JDBC 也提供了这四类事务隔离级别,但默认事务隔离级别对不同数据库产品而言,却是不一样的。我们熟知的 MySQL 数据库的默认事务隔离级别就是 READ_COMMITTED,Oracle、SQL Server、DB2等都有有自己的默认值。我认为 READ_COMMITTED 已经可以解决绝大多数问题了,其他的就具体情况具体分析吧。

若对其他数据库的默认事务隔离级别不太清楚,可以使用以下代码来获取:

DatabaseMetaData meta = DBUtil.getDataSource().getConnection().getMetaData();
int defaultIsolation = meta.getDefaultTransactionIsolation();

提示:在 java.sql.Connection 类中可查看所有的隔离级别。

我们知道 JDBC 只是连接 Java 程序与数据库的桥梁而已,那么数据库又是怎样隔离事务的呢?其实它就是“锁”这个东西。当插入数据时,就锁定表,这叫“锁表”;当更新数据时,就锁定行,这叫“锁行”。当然这个已经超出了我们今天讨论的范围,所以还是留点空间给我们的 DBA 同学吧,免得他没啥好写的了。

除了 JDBC 给我们提供的事务隔离级别这种解决方案以外,还有哪些解决方案可以完善事务管理功能呢?

不妨看看 Spring 的解决方案吧,其实它是对 JDBC 的一个补充或扩展。它提供了一个非常重要的功能,就是:事务传播行为(Transaction Propagation Behavior)

确实够牛逼的,Spring 一下子就提供了 7 种事务传播行为,这 7 种行为一出现,真的是亮瞎了我的狗眼!

  1. PROPAGATION_REQUIRED
  2. RROPAGATION_REQUIRES_NEW
  3. PROPAGATION_NESTED
  4. PROPAGATION_SUPPORTS
  5. PROPAGATION_NOT_SUPPORTED
  6. PROPAGATION_NEVER
  7. PROPAGATION_MANDATORY

看了 Spring 参考手册之后,更是晕了,这到底是在干嘛?

首先要明确的是,事务是从哪里来?传播到哪里去?答案是,从方法 A 传播到方法 B。Spring 解决的只是方法之间的事务传播,那情况就多了,比如:

  1. 方法 A 有事务,方法 B 也有事务。
  2. 方法 A 有事务,方法 B 没有事务。
  3. 方法 A 没有事务,方法 B 有事务。
  4. 方法 A 没有事务,方法 B 也没有事务。

这样就是 4 种了,还有 3 种特殊情况。还是用我的 Style 给大家做一个分析吧:

假设事务从方法 A 传播到方法 B,您需要面对方法 B,问自己一个问题:

方法 A 有事务吗?

  1. 如果没有,就新建一个事务;如果有,就加入当前事务。这就是 PROPAGATION_REQUIRED,它也是 Spring 提供的默认事务传播行为,适合绝大多数情况。
  2. 如果没有,就新建一个事务;如果有,就将当前事务挂起。这就是 RROPAGATION_REQUIRES_NEW,意思就是创建了一个新事务,它和原来的事务没有任何关系了。
  3. 如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。这就是 PROPAGATION_NESTED,也就是传说中的“嵌套事务”了,所嵌套的子事务与主事务之间是有关联的(当主事务提交或回滚,子事务也会提交或回滚)。
  4. 如果没有,就以非事务方式执行;如果有,就使用当前事务。这就是 PROPAGATION_SUPPORTS,这种方式非常随意,没有就没有,有就有,有点无所谓的态度,反正我是支持你的。
  5. 如果没有,就以非事务方式执行;如果有,就将当前事务挂起。这就是 PROPAGATION_NOT_SUPPORTED,这种方式非常强硬,没有就没有,有我也不支持你,把你挂起来,不鸟你。
  6. 如果没有,就以非事务方式执行;如果有,就抛出异常。这就是 PROPAGATION_NEVER,这种方式更猛,没有就没有,有了反而报错,确实够牛的,它说:我从不支持事务!
  7. 如果没有,就抛出异常;如果有,就使用当前事务。这就是 PROPAGATION_MANDATORY,这种方式可以说是牛逼中的牛逼了,没有事务直接就报错,确实够狠的,它说:我必须要有事务!

最后,推荐大家使用 Spring 的注解式事务配置,而放弃 XML 式事务配置。因为注解实在是太优雅了,当然这一切都取决于您自身的情况了。

在 Spring 配置文件中使用:

...
<tx:annotation-driven />
...

数据库事务管理


B tree VS B+ tree


The image below helps show the differences between B+ trees and B trees.

Advantages of B+ trees:

  • Because B+ trees don't have data associated with interior nodes, more keys can fit on a page of memory. Therefore, it will require fewer cache misses in order to access data that is on a leaf node.
  • The leaf nodes of B+ trees are linked, so doing a full scan of all objects in a tree requires just one linear pass through all the leaf nodes. A B tree, on the other hand, would require a traversal of every level in the tree. This full-tree traversal will likely involve more cache misses than the linear traversal of B+ leaves.

Advantage of B trees:

  • Because B trees contain data with each key, frequently accessed nodes can lie closer to the root, and therefore can be accessed more quickly.