|
摘要: 1.可以在servlet的init方法里 String path = getServletContext().getRealPath("/"); 这将获取web项目的全路径 例如 :E:\eclipseM9\workspace\tree\ tree是我web项目的根目录 2.你也可以随时在任意的class里调用 this.getClass... 阅读全文
摘要: Maven带有超过40+个Maven模板,让开发者快速开始一个新的Java项目。这一章,演示怎样使用Maven的命令“mvn archetype:generate”生成一个新的Java Web项目。 下面是使用Maven模板生成项目的步骤。 1、mvn archetype:generate命令 定位到要生成的项目的目录下,如“D:\... 阅读全文
Spring也提供了声明式事务管理。这是通过Spring AOP实现的。 Spring 中进行事务管理的通常方式是利用AOP(面向切片编程)的方式,为普通java类封装事务控制,它是通过动态代理实现的,由于接口是延迟实例化的, spring在这段时间内通过拦截器,加载事务切片。原理就是这样,具体细节请参考jdk中有关动态代理的文档。本文主要讲解如何在spring中进行事务控制。 动态代理的一个重要特征是,它是针对接口的,所以我们的dao要通过动态代理来让spring接管事务,就必须在dao前面抽象出一个接口,当然如果没有这样的接口,那么spring会使用CGLIB来解决问题,但这不是spring推荐的方式,所以不做讨论. 大多数Spring用户选择声明式事务管理。这是最少影响应用代码的选择, 因而这是和非侵入性的轻量级容器的观念是一致的。 从考虑EJB CMT和Spring声明式事务管理的相似以及不同之处出发是很有益的。 它们的基本方法是相似的:都可以指定事务管理到单独的方法;如果需要可以在事务上 下文调用setRollbackOnly()方法。不同之处如下: 不象EJB CMT绑定在JTA上,Spring声明式事务管理可以在任何环境下使用。 只需更改配置文件,它就可以和JDBC、JDO、Hibernate或其他的事务机制一起工作 Spring可以使声明式事务管理应用到普通Java对象,不仅仅是特殊的类,如EJB Spring提供声明式回滚规则:EJB没有对应的特性, 我们将在下面讨论这个特性。回滚可以声明式控制,不仅仅是编程式的 Spring允许你通过AOP定制事务行为。例如,如果需要,你可以在事务 回滚中插入定制的行为。你也可以增加任意的通知,就象事务通知一样。使用 EJB CMT,除了使用setRollbackOnly(),你没有办法能 够影响容器的事务管理 Spring不提供高端应用服务器提供的跨越远程调用的事务上下文传播。如 果你需要这些特性,我们推荐你使用EJB。然而,不要轻易使用这些特性。通常我 们并不希望事务跨越远程调用 回滚规则的概念是很重要的:它们使得我们可以指定哪些异常应该发起自 动回滚。我们在配置文件中,而不是Java代码中,以声明的方式指定。因此,虽然我们仍 然可以编程调用TransactionStatus对象的 setRollbackOnly()方法来回滚当前事务,多数时候我们可以 指定规则,如MyApplicationException应该导致回滚。 这有显著的优点,业务对象不需要依赖事务基础设施。例如,它们通常不需要引 入任何Spring API,事务或其他任何东西。 EJB的默认行为是遇到系统异常(通常是运行时异常), EJB容器自动回滚事务。EJB CMT遇到应用程序异常 (除了java.rmi.RemoteException外的checked异常)时不 会自动回滚事务。虽然Spring声明式事务管理沿用EJB的约定(遇到unchecked 异常自动回滚事务),但是这是可以定制的。 按照我们的测试,Spring声明式事务管理的性能要胜过EJB CMT。 通常通过TransactionProxyFactoryBean设置Spring事务代理。我们需要一个目标对象包装在事务代理中。这个目标对象一般是一个普通Java对象的bean。当我们定义TransactionProxyFactoryBean时,必须提供一个相关的 PlatformTransactionManager的引用和事务属性。 事务属性含有上面描述的事务定义。 <bean id="petStore" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"><ref bean="transactionManager"/></property> <property name="target"><ref bean="petStoreTarget"/></property> <property name="transactionAttributes"> <props> <prop key="insert*">PROPAGATION_REQUIRED,-MyCheckedException</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property></bean> code] 事务代理会实现目标对象的接口:这里是id为petStoreTarget的bean。(使用 CGLIB也可以实现具体类的代理。只要设置proxyTargetClass属性为true就可以。如果目标对象没有实现任何接口,这将自动设置该属性为true。通常,我们希望面向接口而不是类编程。)使用proxyInterfaces属性来限定事务代理来代 理指定接口也是可以的(一般来说是个好想法)。也可以通过从 org.springframework.aop.framework.ProxyConfig继承或所有AOP代理工厂共享 的属性来定制TransactionProxyFactoryBean的行为。 这里的transactionAttributes属性定义在 org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource 中的属性格式来设置。这个包括通配符的方法名称映射是很直观的。注意 insert*的映射的值包括回滚规则。添加的-MyCheckedException 指定如果方法抛出MyCheckedException或它的子类,事务将 会自动回滚。可以用逗号分隔定义多个回滚规则。-前缀强制回滚,+前缀指定提交(这允许即使抛出unchecked异常时也可以提交事务,当然你自己要明白自己 在做什么)。 TransactionProxyFactoryBean允许你通过 “preInterceptors”和“postInterceptors”属性设置“前”或“后”通知来提供额外的 拦截行为。可以设置任意数量的“前”和“后”通知,它们的类型可以是 Advisor(可以包含一个切入点), MethodInterceptor或被当前Spring配置支持的通知类型 (例如ThrowAdvice, AfterReturningtAdvice或BeforeAdvice, 这些都是默认支持的)。这些通知必须支持实例共享模式。如果你需要高级AOP特 性来使用事务,如有状态的maxin,那最好使用通用的 org.springframework.aop.framework.ProxyFactoryBean, 而不是TransactionProxyFactoryBean实用代理创建者。 也可以设置自动代理:配置AOP框架,不需要单独的代理定义类就可以生成类的 代理。 附两个spring的事务配置例子: <prop key="add"> PROPAGATION_REQUIRES_NEW, -MyException </prop> 注:上面的意思是add方法将独占一个事务,当事务处理过程中产生MyException异常或者该异常的子类将回滚该事务。 <prop key="loadAll"> PROPAGATION_SUPPORTS, ISOLATION_READ_COMMITED, Readonly </prop> 注:表示loadAll方法支持事务,而且不会读取没有提交事务的数据。它的数据为只读(这样有助于提高读取的性能) 附A Spring中的所有事务策略 PROPAGATION_MANDATORY PROPAGATION_NESTED PROPAGATION_NEVER PROPAGATION_NOT_SUPPORTED PROPAGATION_REQUIRED PROPAGATION_REQUIRED_NEW PROPAGATION_SUPPORTS 附B Spring中所有的隔离策略: ISOLATION_DEFAULT ISOLATION_READ_UNCOMMITED ISOLATION_COMMITED ISOLATION_REPEATABLE_READ ISOLATION_SERIALIZABL (转载请注明出处:[url=http://www.a9832.com]博彩网[/url] [url=http://www.tswa.org]博彩通[/url])
摘要: java反射与代理 一. 关于数据库. 当今的数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing)、联机分析处理OLAP(On-Line Analytical Processing)。OLTP是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。OLAP是数据仓库系统的主要应用,支持复杂的分析操作... 阅读全文
众所周知,当多个消息消费者(MessageConsumer)同时监听同一个消息队列(Queue)的时候,JMS提供者会在它们之间提供一种负载均衡机制,从而达到可以同时处理多个消息的目的。图一是一个简单的示意图,当消息生产者发送多个消息时,JMS提供者会把这些消息均匀的分发到不同的消息消费者。 图一 JMS负载均衡示意图
一、WebService负载均衡 要在原来的WebService上应用负载均衡,首先应该明确一个前提,就是客户端和服务端应尽可能的不做修改。另外还需要确保可以方便的添加和删除一个Service节点,而不会影响整个应用的运行。庆幸的是WebService调用通常都是无状态的,类似于无状态会话 Bean(Stateless Session Bean)的远程调用,服务端和客户端不需要维持一个会话,也就是说同一个客户端调用多次WebService请求,每个请求可以由不同的Service 为它服务,这样就可以避免Session复制的问题,如果一个Service崩溃了,另一个Service可以继续为客户端服务。 二、将JMS负载均衡应用到WebService中 接下来就把JMS的负载均衡机制应用到WebService当中去,图二是一个整体的框架图,Proxy作为一个WebService的代理来和客户端交互, 而Listener会去掉用具体的WebService,来完成一次WebService方法的调用。 图二 整体框架图
与客户端直接交互的是Proxy,它是一个简单的Servlet,它的作用就是拦截客户端发送过来的请求,提取请求中的SOAP包的内容,然后把它封装成一个消息发送到指定的Queue中去,同时它会等待消息的回复,因为回复的消息中包含着WebService调用返回的结果,后面会详细讲到。当Proxy收到回复消息之后,读取其中的内容并把它返回给客户端,从而完成一个WebService的调用。另外需要注意的是,在这里Proxy需要区分出客户端发出的是GET请求,还是POST请求。如果是GET请求,就有可能是客户端正在获取WebService的WSDL。如果是POST请求,那么通常就是客户端在调用一个WebService方法了。下面是一个简单的Proxy实现: 1 public class ServiceProxy extends HttpServlet { 2 3 private ConnectionFactory factory; 4 5 private Connection connection; 6 7 private Queue queue; 8 9 public void init() throws ServletException { 10 11 super.init(); 12 13 try { 14 15 //在这里为了简单起见,采用了ActiveMQ。在实际的J2EE应用中应通过JNDI查找相应的ConnectionFactory和Queue。||| 16 17 factory = new ActiveMQConnectionFactory("vm://localhost"); 18 19 connection = factory.createConnection(); 20 21 connection.start(); 22 23 queue = new ActiveMQQueue("testQueue"); 24 25 } catch (JMSException e) { 26 27 e.printStackTrace(); 28 29 } 30 31 } 32 33 protected void doGet(HttpServletRequest req, HttpServletResponse resp) { 34 35 if (req.getQueryString().endsWith("wsdl") || req.getQueryString().endsWith("WSDL")) { 36 37 try { 38 39 Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 40 41 Message message = session.createMessage(); 42 43 //这个属性用来标示请求是否是WSDL请求,后面的Listener会根据它来调用具体的WebService。 44 45 message.setBooleanProperty("isWsdl", true); 46 47 message.setJMSReplyTo(session.createTemporaryQueue()); 48 49 session.createProducer(queue).send(message); 50 51 //等待回复消息,它里面包含Service返回的WSDL,这里使用了一个选择器。 52 53 String selector = String.format("JMSCorrelationID=‘%s‘", message.getJMSMessageID()); 54 55 MessageConsumer consumer = session.createConsumer(message.getJMSReplyTo(), selector); 56 57 TextMessage replyMessage = (TextMessage) consumer.receive(); 58 59 //将WSDL返回给客户端。 60 61 resp.getWriter().write(replyMessage.getText()); 62 63 } catch (Exception e) { 64 65 e.printStackTrace(); 66 67 } 68 69 } 70 71 } 72 73 protected void doPost(HttpServletRequest req, HttpServletResponse resp) { 74 75 try { 76 77 //首先从客户端请求中得到SOAP请求部分。 78 79 StringBuffer payLoad = new StringBuffer(); 80 81 BufferedReader reader = req.getReader(); 82 83 String temp; 84 85 while ((temp = reader.readLine()) != null) { 86 87 payLoad.append(temp); 88 89 } 90 91 //将SOAP请求封装成一个消息,发送到Queue。 92 93 Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 94 95 Message message = session.createTextMessage(payLoad.toString()); 96 97 message.setBooleanProperty("isWsdl", false); 98 99 message.setJMSReplyTo(session.createTemporaryQueue()); 100||| 101 session.createProducer(queue).send(message); 102 103 //等待回复,回复的消息中包含着服务端返回的SOAP响应。 104 105 String selector = String.format("JMSCorrelationID=‘%s‘", message.getJMSMessageID()); 106 107 MessageConsumer consumer = session.createConsumer(message.getJMSReplyTo(), selector); 108 109 TextMessage replyMessage = (TextMessage) consumer.receive(); 110 111 //将SOAP响应返回给客户端。 112 113 resp.getWriter().write(replyMessage.getText()); 114 115 } catch (Exception e) { 116 117 e.printStackTrace(); 118 119 } 120 121 } 122 123 } 接下来需要看一下Listener了。对于每一个Service都有一个Listener与之相对应,当一个Listener从Queue中取得一个消息之后,首先应该判断是否是WSDL请求。如果是WSDL请求,则向WebService发送一个GET请求,并将请求的结果,也就是WSDL封装成一个Message回复给Proxy。如果是SOAP请求,则从中取出SOAP请求部分并通过POST方法发送给Service,所得到的返回结果即为Service的SOAP响应,把它回复给Proxy,进而回复给客户端。 下面是Listener的一个简单实现,在这里我们使用了HttpClient来发送GET和POST请求。 1 public class Listener { 2 3 private ConnectionFactory factory; 4 5 private Connection connection; 6 7 private Queue queue; 8 9 private Session session; 10 11 public Listener() throws Exception { 12 13 //为了简单,还是采用了ActiveMQ。 14 15 factory = new ActiveMQConnectionFactory("vm://localhost"); 16 17 connection = factory.createConnection(); 18 19 connection.start(); 20 21 queue = new ActiveMQQueue("testQueue"); 22 23 session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 24 25 } 26 27 public void startUp() throws Exception { 28 29 MessageConsumer consumer = session.createConsumer(queue); 30 31 consumer.setMessageListener(new MessageListener() { 32 33 public void onMessage(Message message) { 34 35 try { 36 37 String response; 38 39 //通过判断isWSDL这个属性来判断是否是WSDL请求。 40 41 if (message.getBooleanProperty("isWsdl")) { 42 43 //如果是WSDL请求,则向服务器发送一个GET请求,并等待WSDL响应结果。 44 45 HttpClient client = new HttpClient();||| 46 47 //具体Service的地址,可以使用properties文件等。 48 49 GetMethod m = new GetMethod("http://localhost:8081/hello?wsdl"); 50 51 client.executeMethod(m); 52 53 response = m.getResponseBodyAsString(); 54 55 } else { 56 57 //如果是SOAP请求,则将SOAP包发送给服务器,并等待SOAP响应。 58 59 HttpClient client = new HttpClient(); 60 61 PostMethod m = new PostMethod("http://localhost:8081/hello"); 62 63 m.setRequestBody(((TextMessage) message).getText()); 64 65 client.executeMethod(m); 66 67 response = m.getResponseBodyAsString(); 68 69 } 70 71 //将WSDL响应或SOAP响应封装成一个消息,回复给Proxy。 72 73 MessageProducer producer = session.createProducer(message.getJMSReplyTo()); 74 75 TextMessage replyMessage = session.createTextMessage(response); 76 77 //设置JMSCorrelationID,Proxy通过它来得到该回复消息。 78 79 replyMessage.setJMSCorrelationID(message.getJMSCorrelationID()); 80 81 producer.send(replyMessage); 82 83 } catch (Exception ex) { 84 85 ex.printStackTrace(); 86 87 } 88 89 } 90 91 }); 92 93 } 94 95 } 三、还需要考虑的 1,如果其中一个Service崩溃,我们需要停止相应的Listener,这一点可以在Listener中做到,例如当Listener访问 Service时出错,它可以等待一段时间以后再去监听Queue,同时把已经取得的消息重新发回到Queue中去,以便让其他的Listener处理。当然也可以将Listener放置到Service端,这样Service崩溃,Listener也就跟着不可用了。 2,如果某一时刻,所有的Service都不可用,Proxy也不应该无限等待下去,而应该设置一个等待回复消息的超时期限,如果这个期限内没有收到回复消息,则表明Service都不可用,同时通知客户端。 3,过期消息的处理,如同上一点,当Service不可用时,Proxy通知客户端出错,但是此时Proxy已经向Queue中发送了一条消息,当Service恢复时,这条消息会被重新处理。我们应该避免这种情况发生,因为这条消息已经过期了。可以设置消息的过期期限小于Proxy等待回复消息的期限,以确保它不会被重新处理。 4,最糟糕的情况就是,Proxy或者Queue崩溃,这样就算Service正常,客户端也会调用失败。 5,效率,既然我们选择了WebService和负载均衡,那就表示我们应该接受它效率相对低下的弱点,在这里需要说明的是JMS并不是效率的瓶颈,因为Listener只负责拿到消息并发送给Service,这时Service还是运行在多线程下的。 (转载请注明出处:[url=http://www.6rfd.com]澳门博彩[/url] [url=http://www.9gds.com]易博网[/url])
hashCode就是我们所说的散列码,使用hashCode算法可以帮助我们进行高效率的查找,例如HashMap,说hashCode之前,先来看看Object类。 我们知道,Object类是java程序中所有类的直接或间接父类,处于类层次的最高点。在Object类里定义了很多我们常见的方法,包括我们要讲的hashCode方法,如下 - public final native Class<?> getClass();
- public native int hashCode();
- public boolean equals(Object obj) {
- return (this == obj);
- }
- public String toString() {
- return getClass().getName() + "@" + Integer.toHexString(hashCode());
- }
注意到hashCode方法前面有个native的修饰符,这表示hashCode方法是由非java语言实现的,具体的方法实现在外部,返回内存对象的地址。
在java的很多类中都会重写equals和hashCode方法,这是为什么呢?最常见的String类,比如我定义两个字符相同的字符串,那么对它们进行比较时,我想要的结果应该是相等的,如果你不重写equals和hashCode方法,他们肯定是不会相等的,因为两个对象的内存地址不一样。
String类的重写的hashCode方法 - public int hashCode() {
- int h = hash;
- if (h == 0) {
- int off = offset;
- char val[] = value;
- int len = count;
-
- for (int i = 0; i < len; i++) {
- h = 31*h + val[off++];
- }
- hash = h;
- }
- return h;
- }
1、这段代码究竟是什么意思? 其实这段代码是这个数学表达式的实现 - s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
s[i]是string的第i个字符,n是String的长度。那为什么这里用31,而不是其它数呢?《Effective Java》是这样说的:之所以选择31,是因为它是个奇素数,如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为与2相乘等价于移位运算。使用素数的好处并不是很明显,但是习惯上都使用素数来计算散列结果。31有个很好的特性,就是用移位和减法来代替乘法,可以得到更好的性能:31*i==(i<<5)-i。现在的VM可以自动完成这种优化。
2、它返回的hashCode有什么特点呢? 可以看到,String类是用它的value值作为参数来计算hashCode的,也就是说,相同的value就一定会有相同的hashCode值。这点也很容易理解,因为value值相同,那么用equals比较也是相等的,equals方法比较相等,则hashCode一定相等。反过来不一定成立。它不保证相同的hashCode一定有相同的对象。
一个好的hash函数应该是这样的:为不相同的对象产生不相等的hashCode。 在理想情况下,hash函数应该把集合中不相等的实例均匀分布到所有可能的hashCode上,要想达到这种理想情形是非常困难的,至少java没有达到。因为我们可以看到,hashCode是非随机生成的,它有一定的规律,就是上面的数学等式,我们可以构造一些具有相同hashCode但value值不一样的,比如说:Aa和BB的hashCode是一样的。
说到这里,你可能会想,原来构造hash冲突那么简单啊,那我是不是可以对HashMap函数构造很多<key,value>不都一样,但具有相同的hashCode,这样的话可以把HashMap函数变成一条单向链表,运行时间由线性变为平方级呢?虽然HashMap重写的hashCode方法比String类的要复杂些,但理论上说是可以这么做的。这也是最近比较热门的Hash Collision DoS事件。 HashMap里重写的hashCode方法 - public final int hashCode() {
- return (key==null ? 0 : key.hashCode()) ^
- (value==null ? 0 : value.hashCode());
- }
(转载请注明出处:[url=http://www.k8764.com]博彩通[/url]
[url=http://www.5sfd.com]e世博[/url])
由于工作需要,要在JS端将JSON对象转化为字符串,并写到用户的COOKIE中,用来保存用户的一些个人操作习惯。便在网上搜寻了一遍,发现方法有很多,有些代码不清晰,看得乱,有些考虑不周全,生成的字符串有问题,便整合了一些好的写法,自己改进了一下。可能还是考虑得不周全,但是感觉常用的类型都考虑了,望大家多多拍砖指点! JSON.stringify(jsonobj),本来是最简便的方法,可是存在浏览器兼容问题(仅适用于IE8+,Chrome 1+,FF 3+)。 var O2String = function (O) {
//return JSON.stringify(jsonobj);
var S = [];
var J = "";
if (Object.prototype.toString.apply(O) === '[object Array]') {
for (var i = 0; i < O.length; i++)
S.push(O2String(O[i]));
J = '[' + S.join(',') + ']';
}
else if (Object.prototype.toString.apply(O) === '[object Date]') {
J = "new Date(" + O.getTime() + ")";
}
else if (Object.prototype.toString.apply(O) === '[object RegExp]' || Object.prototype.toString.apply(O) === '[object Function]') {
J = O.toString();
}
else if (Object.prototype.toString.apply(O) === '[object Object]') {
for (var i in O) {
O[i] = typeof (O[i]) == 'string' ? '"' + O[i] + '"' : (typeof (O[i]) === 'object' ? O2String(O[i]) : O[i]);
S.push(i + ':' + O[i]);
}
J = '{' + S.join(',') + '}';
}
return J;
};
/*-----------------------以下是测试代码-----------------------*/
var jsonStr = O2String(
[
{
"Page": "plan",
"Custom":
[
{
"ItemName": "CustomLabel1",
"ItemContent": 1,
"IsItem": true,
"ItemDate": new Date(1320774905467),
"ItemReg": /[\w]*?/gi,
"ItemFunc": function () { alert("ItemFunc"); }
},
{
"ItemName": "CustomLabel1",
"ItemContent": 1,
"IsItem": true,
"ItemDate": new Date(1320774905467),
"ItemReg": /[\w]*?/gi,
"ItemFunc": function () { alert("ItemFunc"); }
}
]
},
{
"Page": "project",
"Custom":
[
{
"ItemName": "CustomLabel2",
"ItemContent": 2,
"IsItem": false,
"ItemDate": new Date(1320774905467),
"ItemReg": /[\w]*?/gi,
"ItemFunc": function () { alert("ItemFunc"); }
},
{
"ItemName": "CustomLabel2",
"ItemContent": 2,
"IsItem": false,
"ItemDate": new Date(1320774905467),
"ItemReg": /[\w]*?/gi,
"ItemFunc": function () { alert("ItemFunc"); }
}
]
}
]
);
alert(jsonStr);
var jsonObj = eval("(" + jsonStr + ")");
alert(jsonObj.length);
(转载请注明出处:[url=http://www.tdtf.org]易博网 [/url] [url=http://www.k5048.com]博彩网[/url])
现象: 系统突然报连接数过高,基本的现象就是有什么东西被锁了,导致后续的连接都在等待,那么到底是那个会话导致了阻塞那? 可以查看视图v$session ,关注以下几个字段 sid-------------------------被阻塞的进程id status--------------------被阻塞的进程状态 COMMAND--------------被阻塞的进程执行的命令 ROW_WAIT_FILE#----被阻塞的进程对应的rowid所在的数据文件id row_wait_block#-----row_wait_row#对应的rowid所在的表的object id row_wait_obj#-------row_wait_row#对应的rowid所在的表的object id row_wait_row#-----Current row being locked. This column is valid only if the session is currently waiting for another transaction to commit and the value of ROW_WAIT_OBJ# is not -1 .但是准确的说是对应的于rowid的rownum,并非是单纯的rownum blocking_session -----阻塞进程id STATE-------------------被阻塞进程的状态 EVENT#----------------被阻塞进程等待的事件号 EVENT------------------被阻塞进程等待的事件 -----注意create_time是程序自动添加的select t.sid,t.status,t.COMMAND,t.ROW_WAIT_FILE#,t.row_wait_block#,t.row_wait_obj#,t.row_wait_row#,t.blocking_session ,t.STATE,t.EVENT#,t.EVENT from temp_session t where t.BLOCKING_SESSION_STATUS='VALID' and t.create_time=to_date('2012/3/20 18:47:16','yyyy/mm/dd hh24:mi:ss'); SID STATUS COMMAND ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_OBJ# ROW_WAIT_ROW# BLOCKING_SESSION STATE EVENT# EVENT175 620 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention174 616 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention173 615 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention333 1050 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention179 632 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention178 629 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention332 1049 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention171 610 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention166 592 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention165 591 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention164 589 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention现在可以看到885进程阻塞了好多进程,那么要获得到底是那条记录被锁定了那?想要知道某一个表具体被锁定的是哪一行,可以利用上面这几个值,查找出被锁定行的rowid。使用dbms_rowidb包的一个子过程(Subprograms)rowid_createDBMS_ROWID.ROWID_CREATE (rowid_type IN NUMBER,object_number IN NUMBER,relative_fno IN NUMBER,block_number IN NUMBER,row_number IN NUMBER)RETURN ROWID;其中rowid_type的取值为 0 表示生成一个restricted ROWID(pre-oracle8 format); 取值为1 表示生成一个extended ROWID.object_number取值是dba_objects视图中的data_object_id,并不是object_id,也就是说不能用row_wait_obj#.relative_fno取值是Relative文件号,在dba_data_files里可以查到block_number取值是数据文件的块号,也就是v$session中的row_wait_block#的值row_number通过rowid对应出来的rownum,也就是row_wait_row#的值。 接下来找到这些数据rowid_type=1(11g) object_number selectdata_object_id from dba_objects where object_id='77418'
OBJECT_ID TT_BIGINT NOT NULL Dictionary object number of the object.DATA_OBJECT_ID TT_BIGINT Is ignored.----这是11g的文档说明,可以看出,使用object_id就可以relative_fno=8 block_number=row_wait_block# row_number =row_wait_row# select * from table_name t where rowid=(select DBMS_ROWID.ROWID_CREATE(1,77418,8,571147,17) from dual);---得到被锁定的记录;此时查看885进程在做神马?kill之就可以 (转载请注明出处:[url=http://www.k6567.com]e世博[/url] [url=http://www.d9732.com]澳门博彩[/url])
#include <windows.h> #include <stdio.h> LRESULT CALLBACK WinSunProc(//名字可以更改。参数类型不能变 HWND hwnd, // handle to window 窗口句柄 UINT uMsg, // message identifier WPARAM wParam, // first message parameter 消息参数 LPARAM lParam // second message parameter ); /* int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPSTR lpCmdLine, // pointer to command line int nCmdShow // show state of window ); */ int WINAPI WinMain(//Windows程序的入口函数 HINSTANCE hInstance, // handle to current instance 当前实例句柄 HINSTANCE hPrevInstance, // handle to previous instance 前次实例句柄 LPSTR lpCmdLine, // command line 命令行参数 int nCmdShow // show state 显示方式 ) { /* 创建一个完整的窗口需要经过下面四个操作步骤: 1、设计一个窗口类; 2、注册窗口类; 3、创建窗口; 4、显示及更新窗口。 typedef struct _WNDCLASS { UINT style; //类的类型 WNDPROClpfnWndProc; //longpointfunction函数指针 int cbClsExtra; //类的附加内存 int cbWndExtra; //窗口附加内存 HANDLE hInstance; //实例号(句柄) HICON hIcon; //图标句柄 HCURSOR hCursor; //光标句柄 HBRUSH hbrBackground; //画刷句柄 LPCTSTR lpszMenuName; //菜单的名字 LPCTSTR lpszClassName; //类的名字 } WNDCLASS; */ //1、设计一个窗口类; WNDCLASS wndcls;//窗口类 wndcls.style=CS_HREDRAW | CS_VREDRAW;//重画垂直方向、水平方向 wndcls.lpfnWndProc=WinSunProc;//函数地址 wndcls.cbClsExtra=0;//类的附加内存 wndcls.cbWndExtra=0;//窗口的附加内存 wndcls.hInstance=hInstance;//实例号 wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);//图标 设置 wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);//光标 设置 wndcls.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);//画刷的句柄 wndcls.lpszMenuName=NULL;//(菜单名字) wndcls.lpszClassName="VCXTU";//注册类名(longpoint命令行参数)
//2、注册窗口类; RegisterClass(&wndcls);//注册类 /* HWND CreateWindow( LPCTSTR lpClassName, // pointer to registered class name LPCTSTR lpWindowName, // pointer to window name DWORD dwStyle, // window style int x, // horizontal position of window int y, // vertical position of window int nWidth, // window width int nHeight, // window height HWND hWndParent, // handle to parent or owner window HMENU hMenu, // handle to menu or child-window identifier HANDLE hInstance, // handle to application instance LPVOID lpParam // pointer to window-creation data ); */ //3、创建窗口; HWND hwnd;//窗口句柄 hwnd=CreateWindow( "VCXTU",//注册类名(lpszClassName) "湖南省湘潭市湘潭大学",//窗口名字 /* WS_OVERLAPPEDWINDOW: 窗口风格 WS_OVERLAPPED 层叠的 具有标题栏和边框 WS_CAPTION 有标题栏 WS_SYSMENU 带有系统菜单 WS_THICKFRAME 具有可调边框 WS_MINIMIZEBOX 具有最小化按钮 WS_MAXIMIZEBOX) 具有最大化按钮 */ WS_OVERLAPPEDWINDOW,//窗口风格 CW_USEDEFAULT,//窗口水平坐标(缺省的) CW_USEDEFAULT,//窗口垂直坐标(缺省的) 600,//窗口宽度 400,//窗口高度 NULL,// 父窗口句柄(hWndParent/handle to parent or owner window) NULL,// 菜单句柄(handle to menu or child-window identifier) hInstance,//句柄(handle to application instance) NULL//窗口参数(pointer to window-creation data) ); /* BOOL ShowWindow( HWND hWnd, // handle to window int nCmdShow // show state of window ); */ //4、显示及更新窗口。 ShowWindow( hwnd,//窗口句柄 SW_SHOWNORMAL//显示状态 show state of window ); UpdateWindow(hwnd);//可有可无 /* 操作系统将每个事件都包装成一个称为消息的结构体MSG来传递给应用程序 MSG结构定义如下: typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG; */ //消息循环 MSG msg; /* BOOL GetMessage( LPMSG lpMsg, // address of structure with message HWND hWnd, // handle of window UINT wMsgFilterMin, // first message UINT wMsgFilterMax // last message ); */ while( GetMessage( &msg, NULL, 0,//设成0。表示对所有消息都有兴趣 0 ) ) { /* 转换消息。可以将WM_KEYUP/WM_KEYDOWN转换为WM_CHAR消息、产生新消息并放到队列中 BOOL TranslateMessage( CONST MSG *lpMsg // address of structure with message ); */ TranslateMessage(&msg); /* 将收到的消息传到窗口的回调函数:wndcls.lpfnWndProc=WinSunProc;回调函数:WinSunProc LONG DispatchMessage( CONST MSG *lpmsg // pointer to structure with message ); */ DispatchMessage(&msg); } return 0; } LRESULT CALLBACK WinSunProc( HWND hwnd, // handle to window UINT uMsg, // message identifier WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ) { switch(uMsg) { case WM_CHAR://表示按下了某个字符按键 char szChar[20]; sprintf(szChar,"char is %d",wParam);//格式化消息。WM_CHAR中的wParam参数 /* int MessageBox( HWND hWnd, //拥有消息的父窗口 handle of owner window LPCTSTR lpText, //文本 address of text in message box LPCTSTR lpCaption, //标题 address of title of message box UINT uType //消息框的风格 style of message box ); */ MessageBox( hwnd, szChar, "湘潭大学",//标题 MB_OKCANCEL//MB_YESNO//消息框的风格 ); break; case WM_LBUTTONDOWN: MessageBox(hwnd,"鼠标左键点击了","湘潭大学",MB_OKCANCEL); HDC hdc;//句柄 handle to device context /* HDC GetDC( HWND hWnd // handle to a window ); */ hdc=GetDC(hwnd); /* BOOL TextOut( HDC hdc, // handle to device context int nXStart, // x-coordinate of starting position int nYStart, // y-coordinate of starting position LPCTSTR lpString, // pointer to string int cbString // number of characters in string ); */ TextOut(hdc,0,50,"湖南省湘潭市湘潭大学1",strlen("湖南省湘潭市湘潭大学1")); ReleaseDC(hwnd,hdc);//释放DC break; case WM_PAINT://窗口重绘 HDC hDC; PAINTSTRUCT ps; /* HDC BeginPaint( HWND hwnd, // handle to window LPPAINTSTRUCT lpPaint // pointer to structure for paint information ); */ hDC=BeginPaint(hwnd,&ps);//只能在WM_PAINT里面使用 TextOut(hDC,0,0,"湖南省湘潭市湘潭大学hDC",strlen("湖南省湘潭市湘潭大学hDC")); EndPaint(hwnd,&ps);//只能在WM_PAINT里面使用 break; case WM_CLOSE://关闭窗口时响应 if(IDYES==MessageBox(hwnd,"是否真的结束?","湘潭大学",MB_YESNO)) { DestroyWindow(hwnd);//销掉hwnd窗口 还会发送 WM_DESTROY、WM_NCDESTROY 消息 } break; case WM_DESTROY: PostQuitMessage(0);//退出程序 break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0; } (转载请注明出处:[url=http://www.live588.org]淘金盈[/url] [url=http://www.10086money.com]时尚资讯[/url])
|