﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-上善若水-随笔分类-Database</title><link>http://www.blogjava.net/DLevin/category/53969.html</link><description>In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation.
To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra</description><language>zh-cn</language><lastBuildDate>Wed, 11 Nov 2015 12:34:49 GMT</lastBuildDate><pubDate>Wed, 11 Nov 2015 12:34:49 GMT</pubDate><ttl>60</ttl><item><title>使用NamedParameterJdbcTemplate遇到无法使用的坑</title><link>http://www.blogjava.net/DLevin/archive/2015/11/11/428149.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Wed, 11 Nov 2015 10:46:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2015/11/11/428149.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/428149.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2015/11/11/428149.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/428149.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/428149.html</trackback:ping><description><![CDATA[<h2><span style="font-size: 14px; font-weight: normal;">最近一直在捣鼓HBase的项目，之前写了一些代码从数据库加载数据到HBase，所有的代码都跑得好好地，然而今天尝试着换了一个数据库，就跑不通了。通过数据工具，可以发现连接没有问题，而且有部分逻辑很顺利通过了，然而有一些就是卡主了，通过jstack打印出来的信息可以找到这样的堆栈：</span></h2><div style="font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->"runner{object-loader#292}-objecthandler"&nbsp;#323&nbsp;prio=5&nbsp;os_prio=0&nbsp;tid=0x00002aaadc5ec800&nbsp;nid=0x7f62&nbsp;in&nbsp;Object.wait()&nbsp;[0x0000000056ce4000]<br />&nbsp;&nbsp;&nbsp;java.lang.Thread.State:&nbsp;WAITING&nbsp;(on&nbsp;object&nbsp;monitor)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.Object.wait(Native&nbsp;Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.Object.wait(Object.java:502)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1104)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;locked&nbsp;&lt;0x00000007736013e8&gt;&nbsp;(a&nbsp;org.apache.commons.pool.impl.GenericObjectPool$Latch)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)</div>所以开始我怀疑是连接的问题，从网上也找到了一个类型的现象，有人怀疑是DBPC的一个bug导致死锁：http://stackoverflow.com/questions/5714511/deadlock-issue-in-dbcp-deployed-on-tomcat，所以我升级了DBCP版本1.4，然而和这人一样的结果，升级DBCP版本并没有解决问题。简单的看DBCP的代码，都开始怀疑是不是因为没有Spring JdbcTemplate没有正确的把Connection返回回去引起泄漏了，然而也有点感觉不太可能，因为这段代码在其他数据库都跑得好好地，但是我们的数据库版本都是一致的，然而其他配置上也被假设一致了（被忽略的一个重要的点）。<br /><br />后来开始调配置，减少连接数，减少线程数，经过各种组合，发现当把DB读的batch降到1的时候就可以work了，非常诡异的一个问题。从数据工具中查到，如果用batch，得到的SQL是:<br /><div style="font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->SELECT &lt;column&gt;,&nbsp;&lt;column&gt; FROM &lt;table&gt; where&nbsp;iid&nbsp;in&nbsp;(@p0,&nbsp;@p1<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)</div>如果是batch是1的话：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->SELECT&nbsp;&lt;column&gt;,&nbsp;&lt;column&gt;&nbsp;FROM&nbsp;&lt;table&gt;&nbsp;where&nbsp;iid&nbsp;in&nbsp;(@p0)</div>这段SQL语句是这么产生的：<br /><div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="font-size: 13px;">DataSource&nbsp;dataSource = ....</span><br /><span style="font-size: 13px; color: #0000ff;">this</span><span style="font-size: 13px;">.jdbc&nbsp;=&nbsp;</span><span style="font-size: 13px; color: #0000ff;">new</span><span style="font-size: 13px;">&nbsp;NamedParameterJdbcTemplate(dataSource);</span><br />...<br /><div><span style="font-size: 13px;">MapSqlParameterSource parameters = new MapSqlParameterSource();</span></div><div><span style="font-size: 13px;">parameters.addValue("params", paramsMap.keySet());</span></div><span style="font-size: 13px;">jdbc.query("SELECT &lt;columns&gt; FROM &lt;table&gt; where &lt;column&gt; in (:params)";,&nbsp;parameters,&nbsp;</span><span style="font-size: 13px; color: #0000ff;">new</span><span style="font-size: 13px;">&nbsp;ResultSetExtractor&lt;Void&gt;()&nbsp;{<br /></span>....<br /><span style="font-size: 13px;">})</span></div><br />如果是一个batch的话，在jstack堆栈中可以看到它一直在等数据库的返回结果：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->"runner{object-loader#16}-objecthandler"&nbsp;#47&nbsp;prio=5&nbsp;os_prio=0&nbsp;tid=0x0000000006ddd800&nbsp;nid=0x2694&nbsp;runnable&nbsp;[0x0000000045434000]<br />&nbsp;&nbsp;&nbsp;java.lang.Thread.State:&nbsp;RUNNABLE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.SocketInputStream.socketRead0(Native&nbsp;Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.SocketInputStream.socketRead(SocketInputStream.java:116)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.SocketInputStream.read(SocketInputStream.java:170)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.SocketInputStream.read(SocketInputStream.java:141)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.sybase.jdbc3.timedio.RawDbio.reallyRead(Unknown&nbsp;Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.sybase.jdbc3.timedio.Dbio.doRead(Unknown&nbsp;Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.sybase.jdbc3.timedio.InStreamMgr.a(Unknown&nbsp;Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.sybase.jdbc3.timedio.InStreamMgr.doRead(Unknown&nbsp;Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.sybase.jdbc3.tds.TdsProtocolContext.getChunk(Unknown&nbsp;Source)</div>这也解释了第一个堆栈一直停在borrowObject(getConnection)的阶段，因为之前所有的Connection都在数据库堵住没有返回，所以这个线程再拿Connection的时候超过了我设置的最大Connection数，所以就等着拿不到Connection。<br /><br />在后来查了一下不同数据库的JDBC Driver信息(sp_version):<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->jConnect&nbsp;(TM)&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;JDBC(TM)/7.07&nbsp;ESD&nbsp;#4&nbsp;(Build&nbsp;26793)/P/EBF20302/JDK&nbsp;1.6.0/jdbcmain/OPT/Thu&nbsp;Jul&nbsp;&nbsp;5&nbsp;22:08:44&nbsp;PDT&nbsp;2012<br />jConnect&nbsp;(TM)&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;JDBC(TM)/1000/Wed&nbsp;Mar&nbsp;11&nbsp;05:01:24&nbsp;2015&nbsp;PDT</div><br />也就是说这种用法是因为旧的JDBC Driver对NamedParameterJdbcTemplate不完善引起的，这个坑花了我一整天的时间。。。。<img src ="http://www.blogjava.net/DLevin/aggbug/428149.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2015-11-11 18:46 <a href="http://www.blogjava.net/DLevin/archive/2015/11/11/428149.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]MySQL索引背后的数据结构及算法原理</title><link>http://www.blogjava.net/DLevin/archive/2014/07/21/416059.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Mon, 21 Jul 2014 14:10:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2014/07/21/416059.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/416059.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2014/07/21/416059.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/416059.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/416059.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 引用：http://blog.codinglabs.org/articles/theory-of-mysql-index.html摘要本文以MySQL数据库为研究对象，讨论与数据库索引相关的一些话题。特别需要说明的是，MySQL支持诸多存储引擎，而各种存储引擎对索引的支持也各不相同，因此MySQL数据库支持多种索引类型，如BTree索引，哈希索引，全文索引等等。为了避免混乱，本文将只关注于BTre...&nbsp;&nbsp;<a href='http://www.blogjava.net/DLevin/archive/2014/07/21/416059.html'>阅读全文</a><img src ="http://www.blogjava.net/DLevin/aggbug/416059.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2014-07-21 22:10 <a href="http://www.blogjava.net/DLevin/archive/2014/07/21/416059.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Transaction中SQL的顺序引起的死锁</title><link>http://www.blogjava.net/DLevin/archive/2013/10/17/405069.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Thu, 17 Oct 2013 12:49:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2013/10/17/405069.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/405069.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2013/10/17/405069.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/405069.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/405069.html</trackback:ping><description><![CDATA[因为项目的数据更新频率很高，导致经常出现死锁的问题。感觉以下遇到的一种情况比较典型，也比较tricky，计之。<br />
<br />
<strong>
问题描述：</strong><br />
如以下两条非常简单的SQL语句，它们共同组成了一个Transaction，那么在多线程高频率执行时就会引起死锁问题（当然这里要考虑锁的级别问题，一般多类似这种系统都会选择行锁，那么以下引起死锁的条件是两条语句都对同一行操作）：
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->select&nbsp;&lt;column1&gt;&nbsp;from&nbsp;&lt;table&gt;&nbsp;where&nbsp;&lt;column2&gt;&nbsp;=&nbsp;?&nbsp;<br />
update&nbsp;&lt;table&gt;&nbsp;set&nbsp;&lt;column1&gt;&nbsp;=&nbsp;%d&nbsp;where&nbsp;&lt;column2&gt;&nbsp;=&nbsp;'%s'</div>
<br />
<strong>问题分析：</strong><br />
select语句需要&#8220;Shared Lock&#8221;，因而多个线程可以同时进入，而update需要&#8220;Exclusive Lock&#8221;，当两个线程同时执行了select语句，而获得了&#8220;Shared Lock&#8221;，而他们在接下来执行update语句时，都需要获得&#8220;Exclusive Lock&#8221;而产生竞争，导致死锁。<br />
<br />
<strong>解决方案1:</strong><br />
互换他们的顺序，这样，在第一次执行update语句时，他们会竞争"Exclusive Lock"而引起没有得到&#8220;Exclusive Lock&#8221;的线程等待：<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->1,&nbsp;update&nbsp;&lt;table&gt; set &lt;column2&gt; = &lt;column2&gt; + &lt;some value&gt; where &lt;column1&gt; =&nbsp;'%s'&nbsp;<br />
2.&nbsp;select&nbsp;&lt;column1&gt; from&nbsp;&lt;table&gt; where&nbsp;&lt;column2&gt; =&nbsp;?&nbsp;<br />
3. &lt;column1&gt; - &lt;some value&gt; to&nbsp;get&nbsp;the&nbsp;old &lt;column1&gt; value.</div>
<br />
<strong>解决方案2：</strong><br />
采用&#8220;Hold Lock&#8221;方式，即在所有操作之前做一个dummy的update操作，这样可以保证在进Transaction之前需要先获得一个&#8220;Exclusive Lock&#8221;<br />
<br />
<p>&nbsp;</p><img src ="http://www.blogjava.net/DLevin/aggbug/405069.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2013-10-17 20:49 <a href="http://www.blogjava.net/DLevin/archive/2013/10/17/405069.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>