Closed cxwxz closed 9 years ago
目前内部的ByteBuffer的容量是256字节,所以如果索引字段值和主表key的总长度大于256时会出错, 所以目前的设计太死板了,需要调整一下。
目前测试的结果好像不是这个原因,只要是多线程并发就会有出现这个 java.nio.BufferOverflowException 的 异常。 线程越多出现的时间越早。 应该,在线程的控制有上 BUG 引起的,我用单线程跑相同的代码,都不会出现这类异常。
cxwxzhtc
发件人: codefollower 发送时间: 2013-09-05 23:47 收件人: codefollower/Lealone 抄送: cxwxz 主题: Re: [Lealone] 使用二次索引时造成 java.nio.BufferOverflowException (#56) 目前内部的ByteBuffer的容量是256字节,所以如果索引字段值和主表key的总长度大于256时会出错, 所以目前的设计太死板了,需要调整一下。 — Reply to this email directly or view it on GitHub.
是的,HBaseSecondaryIndex里的buffer字段在多线程时会存在并发修改问题, 再加上长度是256,所以就出现了BufferOverflowException。
这是java.nio.HeapByteBuffer类的源代码:
public ByteBuffer put(byte[] src, int offset, int length) {
checkBounds(offset, length, src.length);
if (length > remaining())
throw new BufferOverflowException();
System.arraycopy(src, offset, hb, ix(position()), length);
position(position() + length);
return this;
}
所以这个问题是只要索引字段值和主表key的总长度太长或多个线程并发写都存在问题。 我正在解决这个问题,谢谢你的反馈 :)
这种索引字段值和主表key构成二级索引rowkey的方式能保证二级索引的排序吗? 如果是这样,为什么不考虑在多列做复合键时,用这种方式,而要用UUID呢?
索引表的rowKey和主表的rowKey是不一样的,索引表的rowKey=索引字段值+主表rowKey,肯定能保证顺序。
uuid的主要动机是在表没有primary key时使用, 如果primary key是复合键的情况,将它们组合起来做为rowKey其实意义不大, 比如,如果rowKey是(a、b、c)三个字段组合而成,如果按b或c来查,这样的rowKey没任何意义, 当然,也可以用复合键,不过目前还没有计划很急迫实现这个功能。
如果索引字段值是不定长的字符串,用索引字段值+主表rowkey还能保真顺序吗?
使用多个实例时行并发测试会出现 java.nio.BufferOverflowException
根据提示应该是 二级 索引时引起的。
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [INSERT INTO HBASE_USER (ID,NAME,ORG,DISTRICT) VALUES (?,?,?,?)]; SQL state [HY000]; error code [50000]; General error: "java.nio.BufferOverflowException"; SQL statement: INSERT INTO HBASE_USER (ID,NAME,ORG,DISTRICT) VALUES (?,?,?,?) [50000-171]; nested exception is com.codefollower.lealone.jdbc.JdbcSQLException: General error: "java.nio.BufferOverflowException"; SQL statement: INSERT INTO HBASE_USER (ID,NAME,ORG,DISTRICT) VALUES (?,?,?,?) [50000-171] at com.codefollower.lealone.message.DbException.getJdbcSQLException(DbException.java:330) at com.codefollower.lealone.message.DbException.get(DbException.java:159) at com.codefollower.lealone.message.DbException.convert(DbException.java:282) at com.codefollower.lealone.hbase.command.CommandParallel.throwException(CommandParallel.java:193) at com.codefollower.lealone.hbase.command.CommandParallel.execute(CommandParallel.java:186) at com.codefollower.lealone.hbase.dbobject.table.HBaseTable.addRow(HBaseTable.java:412) at com.codefollower.lealone.command.dml.Insert.insertRows(Insert.java:116) at com.codefollower.lealone.command.dml.Insert.update(Insert.java:85) at com.codefollower.lealone.hbase.command.dml.HBaseInsert.internalUpdate(HBaseInsert.java:70) at com.codefollower.lealone.hbase.command.dml.InsertOrMergeSupport.update(InsertOrMergeSupport.java:123) at com.codefollower.lealone.hbase.command.dml.HBaseInsert.update(HBaseInsert.java:55) at com.codefollower.lealone.hbase.command.RetryableCommand.execute(RetryableCommand.java:44) at com.codefollower.lealone.hbase.command.RetryableCommand.updateInternal(RetryableCommand.java:30) at com.codefollower.lealone.command.CommandContainer.update(CommandContainer.java:76) at com.codefollower.lealone.command.Command.executeUpdate(Command.java:235) at com.codefollower.lealone.command.BackendBatchCommand.executeUpdate(BackendBatchCommand.java:91) at com.codefollower.lealone.server.TcpServerThread.executeBatch(TcpServerThread.java:264) at com.codefollower.lealone.server.TcpServerThread.process(TcpServerThread.java:473) at com.codefollower.lealone.server.TcpServerThread.run(TcpServerThread.java:136) at java.lang.Thread.run(Thread.java:662) Caused by: java.nio.BufferOverflowException at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:165) at java.nio.ByteBuffer.put(ByteBuffer.java:813) at com.codefollower.lealone.hbase.dbobject.index.HBaseSecondaryIndex.encode(HBaseSecondaryIndex.java:240) at com.codefollower.lealone.hbase.dbobject.index.HBaseSecondaryIndex.getKey(HBaseSecondaryIndex.java:180) at com.codefollower.lealone.hbase.dbobject.index.HBaseSecondaryIndex.getKey(HBaseSecondaryIndex.java:163) at com.codefollower.lealone.hbase.dbobject.index.HBaseSecondaryIndex.add(HBaseSecondaryIndex.java:128) at com.codefollower.lealone.hbase.dbobject.table.HBaseTable$1.call(HBaseTable.java:405) at com.codefollower.lealone.hbase.dbobject.table.HBaseTable$1.call(HBaseTable.java:403) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) at java.util.concurrent.FutureTask.run(FutureTask.java:138) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) ... 1 more
Caused by: com.codefollower.lealone.jdbc.JdbcSQLException: General error: "java.nio.BufferOverflowException"; SQL statement: INSERT INTO HBASE_USER (ID,NAME,ORG,DISTRICT) VALUES (?,?,?,?) [50000-171] at com.codefollower.lealone.message.DbException.getJdbcSQLException(DbException.java:330) at com.codefollower.lealone.message.DbException.get(DbException.java:159) at com.codefollower.lealone.message.DbException.convert(DbException.java:282) at com.codefollower.lealone.hbase.command.CommandParallel.throwException(CommandParallel.java:193) at com.codefollower.lealone.hbase.command.CommandParallel.execute(CommandParallel.java:186) at com.codefollower.lealone.hbase.dbobject.table.HBaseTable.addRow(HBaseTable.java:412) at com.codefollower.lealone.command.dml.Insert.insertRows(Insert.java:116) at com.codefollower.lealone.command.dml.Insert.update(Insert.java:85) at com.codefollower.lealone.hbase.command.dml.HBaseInsert.internalUpdate(HBaseInsert.java:70) at com.codefollower.lealone.hbase.command.dml.InsertOrMergeSupport.update(InsertOrMergeSupport.java:123) at com.codefollower.lealone.hbase.command.dml.HBaseInsert.update(HBaseInsert.java:55) at com.codefollower.lealone.hbase.command.RetryableCommand.execute(RetryableCommand.java:44) at com.codefollower.lealone.hbase.command.RetryableCommand.updateInternal(RetryableCommand.java:30) at com.codefollower.lealone.command.CommandContainer.update(CommandContainer.java:76) at com.codefollower.lealone.command.Command.executeUpdate(Command.java:235) at com.codefollower.lealone.command.BackendBatchCommand.executeUpdate(BackendBatchCommand.java:91) at com.codefollower.lealone.server.TcpServerThread.executeBatch(TcpServerThread.java:264) at com.codefollower.lealone.server.TcpServerThread.process(TcpServerThread.java:473) at com.codefollower.lealone.server.TcpServerThread.run(TcpServerThread.java:136) at java.lang.Thread.run(Thread.java:662) Caused by: java.nio.BufferOverflowException at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:165) at java.nio.ByteBuffer.put(ByteBuffer.java:813) at com.codefollower.lealone.hbase.dbobject.index.HBaseSecondaryIndex.encode(HBaseSecondaryIndex.java:240) at com.codefollower.lealone.hbase.dbobject.index.HBaseSecondaryIndex.getKey(HBaseSecondaryIndex.java:180) at com.codefollower.lealone.hbase.dbobject.index.HBaseSecondaryIndex.getKey(HBaseSecondaryIndex.java:163) at com.codefollower.lealone.hbase.dbobject.index.HBaseSecondaryIndex.add(HBaseSecondaryIndex.java:128) at com.codefollower.lealone.hbase.dbobject.table.HBaseTable$1.call(HBaseTable.java:405) at com.codefollower.lealone.hbase.dbobject.table.HBaseTable$1.call(HBaseTable.java:403) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) at java.util.concurrent.FutureTask.run(FutureTask.java:138) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) ... 1 more